Giter Club home page Giter Club logo

powerwechat's Introduction

PowerWeChat SDK

Go Build Go Test

你的Star,是对我们最好的支持!也是我们坚持的动力!


PowerWeChat是一款基于Golang的微信SDK开发框架。目前已经覆盖了微信小程序、企业微信、微信支付等绝大部分场景的API。

PowerWeChat致力于减少微信开发中的各种上手难度,使用者只需要关心API使用,不需要关注底层微信开发中需要用到各种AES加密和解密、签名以及验证,回调通知加解密等。

产品特性

  • 简易上手,安装一次,全覆盖微信功能接口
  • 开源项目,丰富的文档内容,长期维护
  • 大部分接口已经支持强类型覆盖
  • 完整的测试项目,支持Web API测试

快速上手

go get -u github.com/ArtisanCloud/PowerWeChat/v3

示范:初始化实例对象,调用小程序的授权登陆接口

import (
	"github.com/ArtisanCloud/PowerWeChat/v3/src/miniProgram"
	"os"
)

// 1. 初始化小程序应用实例
app, err := miniProgram.NewMiniProgram(&miniProgram.UserConfig{
	AppID:  os.Getenv("miniprogram_app_id"), // 小程序、公众号或者企业微信的appid
	Secret: os.Getenv("miniprogram_secret"), // 商户号 appID
	HttpDebug: true,
	Debug:     false,
})

// 2. 调用小程序的授权登陆接口
code := "CODE" // 前端小程序登录时,从微信获取的code
rs, err := app.Auth.Session(code)

printf(rs.OpenID)

更多实例接口,请打开官方文档

文档以及使用示例

  • 官网文档 :全面的接口文档,方便用户查找,使用我们开发的sdk功能

  • 使用示例 :您可以通过Tutorial来了解到PowerWeChat的配置和使用

    ps: 我们单独写了一个项目 PowerWechatTutorial ,基本上覆盖了大部分常用的API使用,希望能够帮助大家更快的上手Golang WeChat开发。

版本升级描述(V2->V3)

  • 接口添加context参数
  • 解决v2的自动refresh token问题

如果你觉得这个项目对你有帮助,可以请作者喝杯咖啡

请扫我

视频教程

API快速导航

更多内容请在官方文档 里面进行查阅。

产品诞生背景

团队也是很多同学一样,从 PHP 转向 Golang,具体为什么,有什么好处,就不用我这里多介绍了吧。 但是现在因为微信的生态做私域化管理是得天独厚,所以我们公司也开发了蛮多企业微信的功能。只是在转型 golang 的过程中,没有找到像 (easywechat)这样好用的 sdk。所以我们就自己想为 golang 的同学们做一点贡献。产品会长期维护,迭代,希望同学们有兴趣在使用的过程中,多给意见。

Star History

Star History Chart

相关产品推荐

PowerX 基于PowerWechat的客域系统
WeyUI 一套微信生态前端组件库,适配PowerX非常友好
BaiduTrans 百度翻译Go-SDK,AIGC后台提词翻译神器

Contributors

特别感谢 Northseadl为版本3所做的贡献




联系我们

如果有任何意见,欢迎在Github Issue上提供意见反馈。同时,也欢迎扫描下方二维码加入微信讨论群。

产品主要维护者

Michael Hu

请扫我

North Wang

请扫我

powerwechat's People

Contributors

ab1136 avatar alvinqinwen avatar beijibeijing avatar bububa avatar chunshengster avatar fourleaftec avatar gxdvip avatar haonanor avatar itzj86 avatar matrix-x avatar miuchan avatar motian avatar northseadl avatar panw3i avatar siaoynli avatar topfanfan avatar vera-byte avatar vkghj avatar walle-space avatar wallev avatar ziyuandaili avatar zsmhub avatar zy84338719 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

powerwechat's Issues

微信公众号Access_token不支持并发

看了下代码,有重试刷新token机制,如果并发,是不是会重复顶掉之前的token(第一次拿token并发也会出现)。能否抽象Acess_token,调用方自己实现逻辑。
类似下面的代码

type AccessToken interface {
    GetAccessToken() (accessToken string, err error)
    RefreshAccessToken(accessToken string) (accessToken string, err error)
}

希望增加对企微bot接收消息的支持

不过官方的企微bot文档很不完善,只有每个bot点进去那一页,讲推送消息的方法…
接收消息基本没文档
比如message_type除了text和mixed,还能为event,此时event.event_type可能为:

  • enter_chat:用户进入bot私聊
  • add_to_chat:bot被拉群

全网找不到,这俩还是自己试出来的

退款接口无法捕获到错误以及多传了参数导致微信抛错

问题1

CleanShot 2021-08-31 at 00 03 14@2x

如图,红框部分没有进去。预期能在err中捕获到错误然后阻止后面的逻辑,结果是到了c.JSON(200, rs)

问题2

sdk提交给微信的参数多了appid和mchid,导致微信报错

{
    "amount": {
        "currency": "CNY",
        "refund": 1,
        "total": 1
    },
    "appid": "ww16143ea0101327cc",
    "mchid": "1611854988",
    "out_refund_no": "551977893977339565922219",
    "transaction_id": "4200001207202108286046087111"
}

微信支付退款 返回结果:

{
    "code": "PARAM_ERROR",
    "detail": {
        "location": null,
        "value": [
            "/body/appid",
            "/body/mchid"
        ]
    },
    "message": "请求中含有未在API文档中定义的参数"
}

生成小程序二维码接口WXACode.GetUnlimited参数中的特殊字符问题

小程序本身接口是支持部分特殊字符的"最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~,其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式)"
https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.getUnlimited.html#method-http.

但是WXACode.GetUnlimited中scene传参带特殊字符,调用微信接口时会被转义导致微信报40129错误

编译报错

接口版本:v2
当前时间(2022-07-29)默认go get下来的库为[email protected]
镜像仓库为goproxy.cn
此版本库accessToken.go:46:16 baseClient.go:38:16位置存在错误,双返回的request.NewHttpRequest(config)方法只取了一个值

token失效补偿机制

因为微信的access_token只允许一个,如果获取了新的token,上一个会在5分钟左右失效。但是目前sdk没有自动刷新机制,导致提前失效之后除非重启应用,否则不会重新刷新。

参考token失效的错误:

{
  "errcode": 40001,
  "errmsg": "invalid credential, access_token is invalid or not latest rid: 6141b79a-7c6e812d-5514c622",
  "resultcode": "",
  "resultmsg": ""
}

企业微信-获取审批模板详情 Json解析失败

oa.Client.ApprovalTemplate() 返回的response中的 TemplateContent为JsonObject, []*power.HashMap无法解析, 改为*power.HashMap解析成功

  • 报错
http request error:json: cannot unmarshal object into Go struct field ResponseApprovalTemplate.template_content of type []*power.HashMap
  • http debug response
{
    "errcode": 0,
    "errmsg": "ok",
    "template_content": {
        "controls": [
            ...
        ]
    },
    "template_names": [
        ...
    ]
}
 ```

文档描述错误 微信支付->退款->退款接口

paymentService.Refund.Refund(
  transactionID, // 微信支付单号
  refundOutNO, // 商户外部单号
  &object.HashMap{
    "refund": 1, // 退款金额。 必填
    "total": 1, // 总金额。 必填
    "currency": "CNY", // 目前微信只支持CNY
  }, 
  nil,
)

refundOutNO应为自己生成的退款单号不是商户下单号
image
jssdk退款文档

微信菜单的struct 缺少Url属性,一级菜单也有可能是view类型,有url这个字段

type Button struct {
Type string json:"type,omitempty"
Name string json:"name"
Key string json:"key,omitempty"
SubButtons []SubButton json:"sub_button,omitempty"
}
因为没有url,导致发布菜单时被提示button url size ;不用库的这种方式接收数据,通过http.Post组装数据发送一切正常。
type Button struct {
Type string json:"type,omitempty"
Name string json:"name"
Key string json:"key,omitempty"
URL string json:"url,omitempty" #添加这个后,发布菜单成功
SubButtons []SubButton json:"sub_button,omitempty"
}

希望兼容微信jsapi支付接口返回异常时的错误字段

在唤起微信支付时遇到错误返回时 会导致微信response无法读取的错误
希望在目标位置 src/kernel/response/wx.go中的ResponsePayment结构体进行追加

type ResponsePayment struct {
	ReturnCode string `json:"return_code"`
	ReturnMSG  string `json:"return_msg,omitempty"`

	ResultCode string `json:"result_code"` // 是	String(16)	SUCCESS/FAIL
	ErrCode    string `json:"err_code,omitempty"`    // 否	String(32)	SYSTEMERROR--系统错误
	ErrMSG     string `json:"errmsg,omitempty"`
	ErrCodeDes string `json:"err_code_des,omitempty"`
	Code string `json:"code,omitempty"` // 追加
	Message string `json:"message,omitempty"` // 追加
}

微信公众号取消关注事件

好像没看到微信公众号取消关注事件的定义unsubscribe;

const (
CALLBACK_EVENT_SUBSCRIBE = "subscribe"
CALLBACK_EVENT_ENTER_AGENT = "enter_agent"
CALLBACK_EVENT_LOCATION = "LOCATION"
CALLBACK_EVENT_BATCH_JOB_RESULT = "batch_job_result"
CALLBACK_EVENT_CLICK = "click"
CALLBACK_EVENT_VIEW = "view"
CALLBACK_EVENT_SCANCODE_PUSH = "scancode_push"
CALLBACK_EVENT_SCANCODE_WAITMSG = "scancode_waitmsg"
CALLBACK_EVENT_PIC_SYSPHOTO = "pic_sysphoto"
CALLBACK_EVENT_PIC_PHOTO_OR_ALBUM = "pic_photo_or_album"
CALLBACK_EVENT_PIC_WEIXIN = "pic_weixin"
CALLBACK_EVENT_LOCATION_SELECT = "location_select"
CALLBACK_EVENT_OPEN_APPROVAL_CHANGE = "open_approval_change"
CALLBACK_EVENT_SHARE_AGENT_CHANGE = "share_agent_change"
CALLBACK_EVENT_TEMPLATE_CARD_MENU_EVENT = "template_card_menu_event"
)

JSSDK退款API调用时refund_out_no字段未写入到请求body中

  • go version: go1.16.7 darwin/amd64
  • sdk version v1.1.5

调用退款接口

paymentClient, err := utils.NewWXPaymentApp(ctx.Request, params.AppId, NotifyUrl)
	if err != nil {
		panic(err)
	}
	fmt.Println(params.RefundOutNO)
	// 1634095819-969073932
	outRefundNo := fmt.Sprintf("%d-%d", time.Now().Unix(), time.Now().Nanosecond())
	response, err := paymentClient.Refund.Refund("xxxxx", outRefundNo, &power.HashMap{
		"refund":   15,
		"total":    15,
		"currency": "CNY",
	}, &power.HashMap{
		"reason": "技术部退款",
	})

	fmt.Println(response)

根据utils.NewWXPaymentApp()方法中的HttpDebug: true可看到请求参数缺失out_refund_no
image

以及api接口返回信息亦提示
输入源“/body/out_refund_no”映射到字段“商户退款单号”必填性规则校验失败,此字段为必填项
image

小程序的条码/二维码识别的API 调用的微信url 写错了

`// 本接口提供基于小程序的条码/二维码识别的API
// https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/img/img.scanQRCode.html
func (comp *Client) ScanQRCode(imgURL string, img *power.HashMap) (*response.ResponseIMGScanQRCode, error) {

result := &response.ResponseIMGScanQRCode{}

_, err := comp.UploadImage("cv/img/aicrop", imgURL, img, result)

return result, err

}`

url应该是 'cv/img/qrcode'

企业微信内部应用OAuth授权bug list

  1. 使用简单版的返回user, err := WeComApp.OAuth.Provider.ContactFromCode(code), user.GetID()可以正确返回值。但是如果使用详细版user, err := WeComApp.OAuth.Provider.Detailed().ContactFromCode(code),里面user.GetID()获取到的为空。
  2. user.GetRaw()会抛错interface {} is object.HashMap, not *object.HashMap
  3. GetAuthURL()之前需要全局设置WithRedirectURL(callbackUrl),这个在网络请求存在并发的情况下可能导致callbackUrl冲突。
  4. 授权的时候redirect_uri需要被urlencode编码,不然在一些带有特殊字符的情况下导致OAuth2重定向调整出错。

增加下载账单功能

微信文档: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_8.shtml

因为申请交易账单申请资金账单只是返回一个download_urlhash,所以需要再封装一个download接口。

希望能够实现特性:

  • 使用Stream流下载,避免大文件账单直接全部读取导致内存占用过高。
  • 增加自动hash校验功能,如果因为被篡改或者网络错误原因导致hash不对直接抛错。

参考特性:

paymentService.Bill.Download("your/path/to/file-2021-09-01.csv", &power.HashMap{
   "download_url": "https://api.mch.weixin.qq.com/v3/billdownload/file?token=6XIv5TUPto7pByrTQKhd6kwvyKLG2uY2wMMR8cNXqaA_Cv_isgaUtBzp4QtiozLO",
  "hash_type": "SHA1",
  "hash_value": "8823044c286bea726f149bfcfce0b0318122d755",
})

基于上一个申请账单的数据,再下载可避免协程之间并发导致的数据冲突。

微信支付回调闭包优化

出于语言特性的原因,golang里面其他框架如果需要获得当前进程的请求参数,必须是使用者主动传递http.Request
同样,除了web框架之外的其他框架也不能直接响应数据给当次请求,除非使用者主动传递了ResponseWriter进来。

这样导致目前闭包写法显得有点多余,里面判断了一次错误,然后外层还要再捕获一次再处理。

func CallbackWXNotify(c *gin.Context) {
  _, err := services.PaymentApp.HandlePaidNotify(c.Request, func(message *power.HashMap, content *power.HashMap, fail string) interface{} {
    if content == nil || (*content)["out_trade_no"] == nil {
      return "no content notify"
    }
    // 看下支付通知事件状态
    if (*message)["event_type"].(string) != services.TRANSACTION_SUCCESS {
      // 这里可能是微信支付失败的通知,所以可能需要在数据库做一些记录,然后告诉微信我处理完成了。
      return true
    }

    // 查询商户订单号
    orderNO := (*content)["out_trade_no"].(string)
    if orderNO != "" {
      // 这里对照自有数据库里面的订单做查询以及支付状态改变
      log.Printf("订单号:%s 支付成功", orderNO)
    } else {
      // 告诉微信我还没处理成功,等会它会重新发起通知
      // 如果不需要,直接返回true即可
      return "payment fail"
    }
    return true
  })

  if err != nil {
    panic(err)
  }
  c.String(200, "")
}

如上图所示,回调里面的return string表示是出错了,让微信等会重新发起请求, 接着又要在外层判断一次err != nil。

如果去掉闭包,可以直接在return string的那一步就直接抛错,panic或者c.Status(500)都可以,所以建议大致重构成一下以下写法:

  res, err := services.PaymentApp.HandlePaidNotify(c.Request)

  if err != nil {
    panic(err)
  }

  // 看下支付通知事件状态
  if res.eventType != services.TRANSACTION_SUCCESS {
    // 这里可能是微信支付失败的通知,所以可能需要在数据库做一些记录。
  } else {
    // 查询商户订单号
    if res.OutTradeNo != "" {
      // 这里对照自有数据库里面的订单做查询以及支付状态改变
      log.Printf("订单号:%s 支付成功", res.OutTradeNo)
    } else {
      // 告诉微信我还没处理成功,等会它会重新发起通知
      c.String(500, "通信失败,请稍后再通知我")
    }
  }
  c.String(200, "")

我认为重构后的写法会更容易判断流更容易理解

jssdk退款API兼容问题

官方是提供

  • 微信支付订单号 (微信系统的订单号)
  • 商户订单号 (自己系统的订单号)
    二选一进行退款操作,但目前代码中只兼容了 第一种 微信支付订单号进行退款。

看了下源码,这一部分代代码 (src/payment/refund/client.go)

func (comp *Client) Refund(transactionID string, refundOutNO string, amount *power.HashMap, options *power.HashMap) (*response.ResponseRefund, error) {
	
	result := &response.ResponseRefund{}

	body := &object.HashMap{
		"amount": amount,
	}

	if transactionID != "" {
		(*body)["transaction_id"] = transactionID
	} else if refundOutNO != "" {
		(*body)["out_refund_no"] = refundOutNO
	} else {
		return nil, errors.New("please given transaction_id or out_refund_no. ")
	}

	body = object.MergeHashMap(body, options.ToHashMap())

	endpoint := comp.Wrap("/v3/refund/domestic/refunds")
	_, err := comp.PlainRequest(endpoint, nil, "POST", body, false, nil, result)

	return result, err
}

#前提是修复该问题#44 (comment)
改为

/**
  微信退款接口
  transactionID string 微信支付订单号
  outTradeNo string 商户订单号 (原接口未提供)
  refundOutNO string  退款订单号(退款时生成)
  amount *power.HashMap 退款金额相关信息
  options  *power.HashMap 备注相关信息
  reason string 退款原因 (原接口未提供)
*/

func (comp *Client) Refund(transactionID string, outTradeNo string, refundOutNO string, reason string, amount *power.HashMap, options *power.HashMap) (*response.ResponseRefund, error) {

	result := &response.ResponseRefund{}

	body := &object.HashMap{
		"amount": amount,
		"reason": reason,
	}

       // 单方未空 取另一方有值
	if transactionID == "" && outTradeNo != "" {
		(*body)["out_trade_no"] = outTradeNo
	}

        if transactionID != "" && outTradeNo == "" {
		(*body)["transaction_id"] = transactionID
	}

       // 两者皆有值优先取微信支付订单号
	if transactionID != "" && outTradeNo != "" {
		(*body)["transaction_id"] = transactionID
	}

	// 退款订单号是必须的 如果为空返回错误信息 
	if refundOutNO == "" {
		return nil, errors.New("please make sure your refund_out_no field have value")
	}else {
		(*body)["out_refund_no"] = refundOutNO
	}
	
	// todo 校验为何数据未进入到body中
	

	body = object.MergeHashMap(body, options.ToHashMap())

	endpoint := comp.Wrap("/v3/refund/domestic/refunds")
	_, err := comp.PlainRequest(endpoint, nil, "POST", body, false, nil, result)

	return result, err
}

微信API返回HTTP Code为4xx或者5xx时候的处理行为优化

// 下单
response, err := paymentService.Order.JSAPITransaction(&object.HashMap{
	"amount": &object.HashMap{
		"total":    1,
		"currency": "CNY",
	},
	"attach":       "自定义数据说明",
	"description":  "Image形象店-深圳腾大-QQ公仔",
	"mchid":        "1611854986",
	"notify_url":   "https://pay.wangchaoyi.com/wx/notify",
	"out_trade_no": "5519778939773395659222199398", // 这里是商户订单号,不能重复提交给微信
	"payer": &object.HashMap{
		"openid": "oAuaP0TRUMwP169nQfg7XCEAw3HQ",  // 用户的openid, 记得也是动态的。
	},
}, false)

if err != nil {
	log.Printf("error: %s", err)
	c.JSON(400, response)
	return
}

payConf, err := paymentService.JSSDK.BridgeConfig(response.PrepayID, true)
if err != nil {
	panic(err)
}

c.JSON(200, payConf)

请看以上示例代码, 如果在第一步Order.JSAPITransaction步骤,提交给微信的参数有问题。

例如:

  1. 商户订单号重复,返回http code 400。
  2. 签名出错,返回http code 500。

这些微信已经明显抛错的地方,我认为应该是在第一次的err里面需要被自动捕获的。不然目前就存在一个很尴尬的行为,就是明明微信已经提示商户订单号重复,结果后面的JSSDK.BridgeConfig还是拿着空PrepayID去生成签名,最终导致微信前端支付出错。

目前临时补救的行为是在第一次判断err != nil 的时候,再加上一个err != nil || response.PrepayID != "",但我觉得这个会增加使用者的心智负担,使用者不可能记住每个API的额外的判断错误条件,这个预下单的接口是response.PrepayID != "",另外一个可能还是response.ErrCode != 0,最终会导致遗漏判断影响后续的业务流程。

请参考以下php示例代码,如果服务端返回了500,最后会进入catch流程,这个是更符合我们的编程直觉的。

try {
      $client = new \GuzzleHttp\Client();
      $response = $client->request('GET', 'http://httpbin.org/status/500');
      echo $response->getStatusCode(); // 200
      echo $response->getHeaderLine('content-type'); // 'application/json; charset=utf8'
      echo $response->getBody(); // '{"id": 1420053, "name": "guzzle", ...}'
  } catch (Exception $exception) {
      dump("出错了");
      dd($exception);
  }

所以我认为应该参考php guzzle的做法,对于4xx5xx的行为做一次err捕获,让用户只判断一个err != nil就可以开始处理错误,至于是系统级错误或者是业务错误,再让使用者在里面进行判断。

Best Wish!

v3 api接口部分请求方法错误

微信支付v3 api对请求方法有强制要求,如两个查询订单接口,微信接口要求使用GET方法

当前client中使用POST发起查询,微信返回405 Method not allowed

关于微信支付版本疑问

我看文档指向路径好像并不是v3
powerWechat是做的老版微信支付接口吗
考虑v3吗 ?
最近微信支付又有了一些改动, 例 企业付款到零钱关闭新商户开通了

关于分账参数中:接收方传参问题

非常感谢 ArtisanCloud 团队开发的 PowerWeChat,我有以下一个问题想咨询?

问题描述:

在微信支付中,为什么分账接收方的 Receivers 参数的类型不是切片?

p.payment.ProfitSharing.Share(&request.RequestShare{
		AppID:           "",
		TransactionID:   "",
		OutOrderNO:      "",
		Receivers:       &request.Receivers{}, // 为什么分账接收方的Receivers类型不是切片?
		UnfreezeUnSplit: true
	})

[doc] 希望文档做相应变更

昨天直接使用官方文档 demo 直接 panic,改成 v2 版本才解决。

import "github.com/ArtisanCloud/PowerWeChat/src/work/message/request" // 需要改为 v2 版本

messages := &request.RequestMessageSendText{
  RequestMessageSend: request.RequestMessageSend{
    ToUser:                 "UserID1|UserID2|UserID3",
    ToParty:                "PartyID1|PartyID2",
    ToTag:                  "TagID1 | TagID2",
    MsgType:                "text",
    AgentID:                1,
    Safe:                   0,
    EnableIDTrans:          0,
    EnableDuplicateCheck:   0,
    DuplicateCheckInterval: 1800,
  },
  Text: &request.RequestText{
    Content: "你的快递已到,请携带工卡前往邮件中心领取。\n出发前可查看<a href=\"http://work.weixin.qq.com\">邮件中心视频实况</a>,聪明避开排队。",
  },
}
WeComApp.Message.SendText(messages)

https://powerwechat.artisan-cloud.com/zh/wecom/message.html#%E5%8F%91%E9%80%81%E5%BA%94%E7%94%A8%E6%B6%88%E6%81%AF

query参数被改变了

POST /wxa/generate_urllink?access_token=62_qSoBD
HTTP/1.1

Content-Type: application/json

{
"cloud_base": null,
"env_version": "release",
"expire_interval": 1668158616,
"expire_type": 1,
"path": "pages/storedata/index",
"query": "FA=FAF\u0026mini_card_id=123"
}

{
"errcode": 40212,
"errmsg": "invalid query rid: 636e146b-3b26fb4a-11dfc7b4"
}

原始query:FA=FAF&mini_card_id=123

小程序直播接口参数和返回类型增加

问题原因:

由于微信小程序直播部分存在文档缺陷,所有接口都是相同的传参和返回值。

例如:

等页面中,文档都是一样的,只是api名字换了一下。

解决办法:

微信的直播文档在平台能力那边,所以需要重新根据小程序直播里面的文档重新封装sdk。

发起退款的接口 response 结构体声明错误

根据文档 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_9.shtml
此处结构体文件

应为数组类型。
image
目前的接口如果用户使用了优惠会导致解析报错:
http request error:json: cannot unmarshal array into Go struct field RefundPromotionDetail.promotion_detail.goods_detail of type struct { MerchantGoodsID string "json:\"merchant_goods_id\""; WechatPayGoodsID string "json:\"wechatpay_goods_id\""; GoodsName string "json:\"goods_name\""; UnitPrice int "json:\"unit_price\""; RefundAmount int "json:\"refund_amount\""; RefundQuantity int "json:\"refund_quantity\"" }

以下 JSON 是服务器返回的 JSON 样例:
{ "amount": { "currency": "CNY", "discount_refund": 700, "from": [], "payer_refund": 14200, "payer_total": 14200, "refund": 14900, "refund_fee": 80, "settlement_refund": 14900, "settlement_total": 14900, "total": 14900 }, "channel": "ORIGINAL", "create_time": "2022-12-08T14:08:15+08:00", "funds_account": "AVAILABLE", "out_refund_no": "ORDERNO123456", "out_trade_no": "ORDERNO123456", "promotion_detail": [ { "amount": 600, "goods_detail": [], "promotion_id": "39542421", "refund_amount": 600, "scope": "GLOBAL", "type": "COUPON" }, { "amount": 100, "goods_detail": [], "promotion_id": "3958275", "refund_amount": 100, "scope": "GLOBAL", "type": "COUPON" } ], "refund_id": "50302", "status": "SUCCESS", "success_time": "2022-12-08T14:08:24+08:00", "transaction_id": "420000159", "user_received_account": "xx银行借记卡1234" }

常见问题解答:

V3支持“超时请求取消机制”

V3增加了context,可以通过context来控制timeout超时请求后,强制取消该词业务请求

// ------ 比如 强制取消获取部门列表接口 ------
ctx,cancel := context.WithTimeout(context.Background(), 1*time.Second)
dept,err := wechatWork.Department.List(ctx, id)



// ------ PowerLib中的单元测试 ------
func TestDataflow_WithContext(t *testing.T) {
	df := InitBaseDataflow()

	ctx, cancel := context.WithCancel(context.Background())

	done := make(chan struct{}, 1)

	go func() {
		time.Sleep(time.Second * 1)
		_, err := df.WithContext(ctx).Request()
		if !errors.Is(err, context.Canceled) {
			t.Error("cancel failed")
		}
		done <- struct{}{}
	}()

	cancel()
	select {
	case <-done:
	}
}

初始化报错 illegal base64 data at input byte 0

这个是由于Token和AESKey没有配置导致的,这个在公众号、企业微信配置里面都有这个参数,用来消息回调解密用。如果暂时不用消息解密,随便设置一个字符串进去即可。

例如:

officialAccount.NewOfficialAccount(&officialAccount.UserConfig{
	AppID:  conf.OffiAccount.AppID,     // 小程序、公众号或者企业微信的appid
	Secret: conf.OffiAccount.AppSecret, // 商户号 appID

	Token:  "xxx",
	AESKey: "xxx",

	ResponseType: os.Getenv("response_type"),
	Log: officialAccount.Log{
		Level: "debug",
		File:  "./wechat.log",
	},
	Cache:     cache,
	HttpDebug: true,
	Debug:     false,
	//"sandbox": true,
})

怎么判断指针类型是否存在?

MiniProgramApp.Auth.Session 返回的errcode不存在 直接通过err判断不了 errcode不为0的情况

session, err := s.MiniProgramApp.Auth.Session(ctx.Request.Context(), reqParams.Code)
if err != nil {
return nil, err
}
if session.ErrCode != 0 {
     return nil, errors.New(session.ErrMsg)
}

session.ErrCode 判断报错 请问怎么解决啊?

在发布微信菜单,url中含有了&符号,会被转义为\u0026,导致发布失败

在发布微信菜单,url中含有了&符号,会被转义为\u0026,导致发布失败;
{
"errcode": 40033,
"errmsg": "invalid charset. please check your request, if include \uxxxx will create fail! rid: 6351f0e3-4fa90897-25a38569"
}
然后用http.Post原始的请求发布,并没有这种问题,通过调试,发现是因为请求中json编码后会有这个问题存在。
感谢官方提供这么好用的库。也希望能解决这个bug

被动回复验证接口 get method 直接返回 success 导致无法通过企业微信验证的问题

使用官方 demo,验证企业微信应用回调,总是返回 success(简单 curl 一下也是),(企业微信官方应该是要原文返回)

demo:

https://github.com/ArtisanCloud/PowerWechatTutorial/blob/master/controllers/wecom/user/user-callback.go#L16

PowerWeChat 版本:v2.0.1-beta8

image

image

看起来是 bug,也有可能我使用的姿势不对?

还望解答一下,感谢 @Matrix-X @EveCoffee

微信公众号使用安全模式,服务端回复信息微信无法解析

问题产生:在微信公众号中开启安全模式(明文模式没问题)
结果:服务器输出的xml为加密格式,微信无法正确识别
代码位置:serverGuard.go 382行
`if serverGuard.IsSafeMode(request) {
// tbd log here
encryptor := (*serverGuard.App).GetComponent("Encryptor").(*Encryptor)
encryptedResponse, err := encryptor.Encrypt(response, "", "")
if err == nil {

		response = string(encryptedResponse)
	} else {
		// tbd log here
		println("encryptor error: ", err.ErrMsg)
	}

}`

当把这个注释时,安全模式可以正常返回消息

同学,您这个项目引入了59个开源组件,存在1个漏洞,辛苦升级一下

检测到 ArtisanCloud/PowerWeChat 一共引入了59个开源组件,存在1个漏洞

漏洞标题:Gin-Gonic Gin 环境问题漏洞
缺陷组件:github.com/gin-gonic/[email protected]
漏洞编号:CVE-2020-28483
漏洞描述:Gin-Gonic Gin是Gin-Gonic团队的一个基于Go语言的用于快速构建Web应用的框架。
github.com/gin-gonic/gin 全部版本存在安全漏洞,该漏洞源于可以通过设置X-Forwarded-For头来欺骗客户端的IP。
影响范围:(∞, 1.7.7)
最小修复版本:1.7.7
缺陷组件引入路径:github.com/ArtisanCloud/PowerWeChat@->github.com/gin-gonic/[email protected]

另外还有几个漏洞,详细报告:https://mofeisec.com/jr?p=a1996d

为什么WeComApp.Server.Notify()接收企微审批状态变更回调消息解析出来的数据是空的?

WeComApp.Server.Notify()接收企微审批状态变更回调消息解析出来的数据是空的
`rs, err := pwWechat.WeComApp.Server.Notify(c.Request, func(event contract.EventInterface) interface{} {
fmt.Dump("event", event)
// kernel.Encryptor(event)
msg := models1.EventOpenApprovalChange{}
err := event.ReadMessage(&msg)
if err != nil {
println(err.Error())
return "error"
}
fmt.Dump(msg)
return kernel.SUCCESS_EMPTY_RESPONSE

})`

{ "EventInterface": null, "XMLName": { "Space": "", "Local": "" }, "Text": "", "ToUserName": "ww674ab0ba94f03533", "FromUserName": "sys", "CreateTime": "1659066539", "MsgType": "event", "Event": "sys_approval_change", "ChangeType": "", "Content": null, "AgentID": "3010040", "ApprovalInfo": { "Text": "", "ThirdNo": "", "OpenSpName": "", "OpenTemplateID": "", "OpenSpStatus": "", "ApplyTime": "1658900033", "ApplyUserName": "", "ApplyUserID": "", "ApplyUserParty": "", "ApplyUserImage": "", "ApprovalNodes": { "Text": "", "ApprovalNode": { "Text": "", "NodeStatus": "", "NodeAttr": "", "NodeType": "", "Items": { "Text": "", "Item": { "Text": "", "ItemName": "", "ItemUserID": "", "ItemImage": "", "ItemStatus": "", "ItemSpeech": "", "ItemOpTime": "" } } } }, "NotifyNodes": { "Text": "", "NotifyNode": { "Text": "", "ItemName": "", "ItemUserID": "", "ItemImage": "" } }, "Approverstep": "" } }

期望增加企微上传文件接口

逛了一圈,只有powerwechat的文档最清晰,赞一个!

期望增加企微上传文件接口。
上传方法缺失的话,只能发送文本消息,很多send方法都不能用。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.