Documentation ¶
Index ¶
- Constants
- func AbsURL(r *http.Request) (url string)
- func AsV3PayApiError(err error, apiError *V3PayApiError) (is bool)
- func EncodeSign(values url.Values, apikey string) string
- func I642P(i int64) *int64
- func P2S(p *string) string
- func P2T(t *time.Time) time.Time
- func S2P(s string) *string
- func UUID32() string
- type APICenterControlAccessTokenReply
- type APICenterControlClient
- type APICenterControlConfig
- type APICenterControlTicketReply
- type Cacher
- type SnsAPIError
- type SnsClient
- func (dep SnsClient) CoreSend(ctx context.Context, fnName string, method xhttp.Method, domain string, ...) (httpResult xhttp.HttpResult, apiError *SnsAPIError, err error)
- func (dep SnsClient) Jscode2session(ctx context.Context, req SnsJscode2sessionRequest) (reply SnsJscode2sessionReply, httpResult xhttp.HttpResult, ...)
- func (dep SnsClient) Oauth2AccessToken(ctx context.Context, req SnsOauth2AccessTokenRequest) (reply SnsOAuth2AccessTokenReply, httpResult xhttp.HttpResult, ...)
- func (dep SnsClient) Oauth2Authorize(req SnsOauth2AuthorizeRequest) (redirectURL string, err error)
- func (dep SnsClient) UserInfo(ctx context.Context, req SnsUserInfoRequest) (reply SnsUserInfoReply, httpResult xhttp.HttpResult, apiError *SnsAPIError, ...)
- type SnsConfig
- type SnsConfigDomain
- type SnsJscode2sessionReply
- type SnsJscode2sessionRequest
- type SnsOAuth2AccessTokenReply
- type SnsOauth2AccessTokenRequest
- type SnsOauth2AuthorizeRequest
- type SnsUserInfoReply
- type SnsUserInfoRequest
- type V3PayApiError
- type V3PayClient
- func (dep V3PayClient) Notify(ctx context.Context, request *http.Request) (tx payments.Transaction, err error)
- func (dep V3PayClient) Refunds(ctx context.Context, req V3RefundsRequest) (refundResp refunddomestic.Refund, httpResult xhttp.HttpResult, ...)
- func (dep V3PayClient) TransactionsJSAPI(ctx context.Context, req V3TransactionsJSAPIRequest) (reply V3TransactionsJSAPIReply, httpResult xhttp.HttpResult, ...)
- func (dep V3PayClient) TransferBatches(ctx context.Context, req V3TransferBatchesRequest) (reply V3TransferBatchesReply, httpResult xhttp.HttpResult, ...)
- func (dep V3PayClient) V3H5Pay(ctx context.Context, req h5.PrepayRequest) (reply *h5.PrepayResponse, httpResult xhttp.HttpResult, apiError *V3PayApiError, ...)
- type V3PayConfig
- type V3RefundsRequest
- type V3TransactionsJSAPIReply
- type V3TransactionsJSAPIRequest
- type V3TransactionsJSAPIRequestAmount
- type V3TransactionsJSAPIRequestPayer
- type V3TransferBatchesReply
- type V3TransferBatchesRequest
- type V3TransferBatchesRequestDetail
Examples ¶
Constants ¶
const IndexCgiBinToken = "/cgi-bin/token"
const IndexCgiTicketGetTicket = "/cgi-bin/ticket/getticket"
const IndexConnectOauth2Authorize = "/connect/oauth2/authorize"
const IndexSnsJscode2session = "/sns/jscode2session"
const IndexSnsOauth2Access_token = "/sns/oauth2/access_token"
const IndexSnsUserInfo = "/sns/userinfo"
const IndexV3PayTransactionJSAPI = "/v3/pay/transactions/jsapi"
const IndexV3TransferBatches = "/v3/transfer/batches"
Variables ¶
This section is empty.
Functions ¶
func AsV3PayApiError ¶
func AsV3PayApiError(err error, apiError *V3PayApiError) (is bool)
Types ¶
type APICenterControlAccessTokenReply ¶
type APICenterControlAccessTokenReply struct {
AccessToken string
}
type APICenterControlClient ¶
type APICenterControlClient struct { Cache Cacher // contains filtered or unexported fields }
APICenterControlClient 微信中控服务客户端 https://github.com/goclub/wx-api-center-control
func NewAPICenterControlClient ¶
func NewAPICenterControlClient(config APICenterControlConfig) (client *APICenterControlClient, err error)
NewAPICenterControlClient 初始化微信中控服务客户端
Example ¶
package main import ( "context" wx "github.com/goclub/wechat" "log" ) func main() { err := func(ctx context.Context) (err error) { config := wx.APICenterControlConfig{ Domain: "使用 https://github.com/goclub/wx-api-center-control 部署的中控服务器域名", SK: "**", } var client *wx.APICenterControlClient if client, err = wx.NewAPICenterControlClient(config); err != nil { return } appid := "wx********" log.Print(client.Ticket(ctx, appid, "jsapi")) log.Print(client.AccessToken(ctx, appid)) return }(context.Background()) log.Printf("%+v", err) }
Output:
func (APICenterControlClient) AccessToken ¶
func (client APICenterControlClient) AccessToken(ctx context.Context, appid string) (reply APICenterControlAccessTokenReply, err error)
AccessToken 获取access_token https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。
func (APICenterControlClient) Ticket ¶
func (client APICenterControlClient) Ticket(ctx context.Context, appid string, ticketType string) (reply APICenterControlTicketReply, err error)
Ticket https://developers.weixin.qq.com/doc/offiaccount/WeChat_Invoice/Nontax_Bill/API_list.html#2.1 ticket用于加强安全性。ticket的有效期目前为2个小时,需定时刷新。建议公众号开发者使用中控服务器统一获取和刷新ticket。
type APICenterControlConfig ¶
type APICenterControlTicketReply ¶
type APICenterControlTicketReply struct {
Ticket string
}
type SnsAPIError ¶
func (*SnsAPIError) Error ¶
func (e *SnsAPIError) Error() string
func (SnsAPIError) Struct ¶
func (e SnsAPIError) Struct() SnsAPIError
type SnsClient ¶
type SnsClient struct {
// contains filtered or unexported fields
}
func NewSnsClient ¶
func (SnsClient) CoreSend ¶
func (dep SnsClient) CoreSend( ctx context.Context, fnName string, method xhttp.Method, domain string, path string, request xhttp.SendRequest, resp interface { Error() string Struct() SnsAPIError }, ) (httpResult xhttp.HttpResult, apiError *SnsAPIError, err error)
func (SnsClient) Jscode2session ¶
func (dep SnsClient) Jscode2session(ctx context.Context, req SnsJscode2sessionRequest) (reply SnsJscode2sessionReply, httpResult xhttp.HttpResult, apiError *SnsAPIError, err error)
Jscode2session 小程序登录 code2Session https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-login/code2Session.html 登录凭证校验。通过 wx.login 接口获得临时登录凭证 code 后传到开发者服务器调用此接口完成登录流程。更多使用方法详见小程序登录。
Example ¶
err := func(ctx context.Context) (err error) { var client *wx.SnsClient if client, err = NewSnsClient(); err != nil { return } var apiError *wx.SnsAPIError var httpResult xhttp.HttpResult var reply wx.SnsJscode2sessionReply if reply, httpResult, apiError, err = client.Jscode2session(ctx, wx.SnsJscode2sessionRequest{ Code: "", Appid: "", Secret: "", }); err != nil { return } if apiError != nil { log.Print("接口错误:\n", apiError.Error()) log.Print("http:\n", httpResult.DumpRequestResponseString(true)) return apiError } // Unionid 绑定了微信开放平台才会有 // reply.Unionid xjson.PrintIndent("reply", reply) return }(context.Background()) log.Printf("%+v", err)
Output:
func (SnsClient) Oauth2AccessToken ¶
func (dep SnsClient) Oauth2AccessToken(ctx context.Context, req SnsOauth2AccessTokenRequest) (reply SnsOAuth2AccessTokenReply, httpResult xhttp.HttpResult, apiError *SnsAPIError, err error)
Oauth2AccessToken 第二步:通过code换取网页授权access_token https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html#1
Example ¶
err := func(ctx context.Context) (err error) { var client *wx.SnsClient if client, err = NewSnsClient(); err != nil { return } var apiError *wx.SnsAPIError var httpResult xhttp.HttpResult var reply wx.SnsOAuth2AccessTokenReply if reply, httpResult, apiError, err = client.Oauth2AccessToken(ctx, wx.SnsOauth2AccessTokenRequest{ Domain: "", Code: "", Appid: "", Secret: "", }); err != nil { return } if apiError != nil { log.Print("接口错误:\n", apiError.Error()) log.Print("http:\n", httpResult.DumpRequestResponseString(true)) return apiError } // 微信快照用户不要走登录的逻辑 // 因为让快照用户登录可能会出现串号(A与B使用的是同一个快照用户)并且都是假用户获取user info 可能会微信报错 if reply.IsSnapshotUser == 1 { return xerr.New("在这里给用户渲染 本项目下的 snapshot_user_page.html 文件") } xjson.PrintIndent("reply", reply) return }(context.Background()) log.Printf("%+v", err)
Output:
func (SnsClient) Oauth2Authorize ¶
func (dep SnsClient) Oauth2Authorize(req SnsOauth2AuthorizeRequest) (redirectURL string, err error)
Oauth2Authorize 第一步:用户同意授权,获取code https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html#0
func (SnsClient) UserInfo ¶
func (dep SnsClient) UserInfo(ctx context.Context, req SnsUserInfoRequest) (reply SnsUserInfoReply, httpResult xhttp.HttpResult, apiError *SnsAPIError, err error)
UserInfo 第四步:拉取用户信息(需scope为 snsapi_userinfo)
Example ¶
err := func(ctx context.Context) (err error) { var client *wx.SnsClient if client, err = NewSnsClient(); err != nil { return } var apiError *wx.SnsAPIError var httpResult xhttp.HttpResult var reply wx.SnsUserInfoReply if reply, httpResult, apiError, err = client.UserInfo(ctx, wx.SnsUserInfoRequest{ // 通过 client.Oauth2AccessToken(code) 获取 token AccessToken: "xxx", // 通过 client.Oauth2AccessToken(code) 获取 openid OpenID: "***", Lang: "zh_CN", }); err != nil { return } if apiError != nil { log.Print("接口错误:\n", apiError.Error()) log.Print("http:\n", httpResult.DumpRequestResponseString(true)) return apiError } // 实践 // 只有在用户将公众号绑定到微信开放平台帐号后,才会出现 UnionID 该字段。 // https://open.weixin.qq.com/ 注意是开放平台不是公众平台 // reply.UnionID // 微信公众平台用户信息相关接口调整公告官方: 公众号用户信息获取接口:不再返回用户性别及地区信息; // https://developers.weixin.qq.com/community/develop/doc/00028edbe3c58081e7cc834705b801 xjson.PrintIndent("reply", reply) return }(context.Background()) log.Printf("%+v", err)
Output:
type SnsConfig ¶
type SnsConfig struct {
Domain SnsConfigDomain
}
type SnsConfigDomain ¶
type SnsJscode2sessionReply ¶
type SnsJscode2sessionReply struct { Openid string `json:"openid"` SessionKey string `json:"session_key"` // 用户在开放平台的唯一标识符,若当前小程序已绑定到微信开放平台帐号下会返回,详见 UnionID 机制说明。 // https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/union-id.html Unionid string `json:"unionid" note:"绑定了微信开放平台才会有"` }
type SnsOAuth2AccessTokenReply ¶
type SnsOAuth2AccessTokenReply struct { AccessToken string `json:"access_token"` ExpiresIn int64 `json:"expires_in"` Openid string `json:"openid"` RefreshToken string `json:"refresh_token"` Scope string `json:"scope"` // 注意!快照用户可能会导致串号,请参考一下链接 // https://developers.weixin.qq.com/community/minihome/doc/000c2c34068880629ced91a2f56001 // https://developers.weixin.qq.com/community/minihome/doc/0008ee0584489030956ea3bba5ec00?source=indexmixflow IsSnapshotUser int `` /* 133-byte string literal not displayed */ }
type SnsOauth2AuthorizeRequest ¶
type SnsOauth2AuthorizeRequest struct { RedirectURL string AppID string Scope string `eg:"snsapi_base,snsapi_userinfo"` SourceURL string State string ForcePopup bool // 快照模式 https://developers.weixin.qq.com/community/minihome/doc/000c2c34068880629ced91a2f56001?page=4#comment-list ForceSnapShot bool }
type SnsUserInfoReply ¶
type SnsUserInfoReply struct { // 微信公众平台用户信息相关接口调整公告官方: 公众号用户信息获取接口:不再返回用户性别及地区信息; // https://developers.weixin.qq.com/community/develop/doc/00028edbe3c58081e7cc834705b801 Openid string `json:"openid"` Nickname string `json:"nickname"` Headimgurl string `json:"headimgurl"` Privilege []string `json:"privilege"` UnionID string `json:"unionid" note:"只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。"` }
type SnsUserInfoRequest ¶
type V3PayApiError ¶
type V3PayApiError struct { StatusCode int // 应答报文的 HTTP 状态码 Header http.Header // 应答报文的 Header 信息 Body string // 应答报文的 Body 原文 Code string `json:"code"` // 应答报文的 Body 解析后的错误码信息,仅不符合预期/发生系统错误时存在 Message string `json:"message"` // 应答报文的 Body 解析后的文字说明信息,仅不符合预期/发生系统错误时存在 Detail interface{} `json:"detail,omitempty"` // 应答报文的 Body 解析后的详细信息,仅不符合预期/发生系统错误时存在 }
func (*V3PayApiError) Error ¶
func (e *V3PayApiError) Error() string
type V3PayClient ¶
type V3PayClient struct { Client *core.Client Handler *notify.Handler // contains filtered or unexported fields }
func NewV3PayClient ¶
func NewV3PayClient(config V3PayConfig) (client *V3PayClient, err error)
func (V3PayClient) Notify ¶
func (dep V3PayClient) Notify(ctx context.Context, request *http.Request) (tx payments.Transaction, err error)
func (V3PayClient) Refunds ¶
func (dep V3PayClient) Refunds(ctx context.Context, req V3RefundsRequest) (refundResp refunddomestic.Refund, httpResult xhttp.HttpResult, apiError *V3PayApiError, err error)
func (V3PayClient) TransactionsJSAPI ¶
func (dep V3PayClient) TransactionsJSAPI(ctx context.Context, req V3TransactionsJSAPIRequest) (reply V3TransactionsJSAPIReply, httpResult xhttp.HttpResult, apiError *V3PayApiError, err error)
TransactionsJSAPI https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_1.shtml 商户系统先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易会话标识后再按Native、JSAPI、APP等不同场景生成交易串调起支付。
Example ¶
err := func(ctx context.Context) (err error) { var client *wx.V3PayClient if client, err = NewV3PayClient(); err != nil { return } var apiError *wx.V3PayApiError var httpResult xhttp.HttpResult var resp wx.V3TransactionsJSAPIReply if resp, httpResult, apiError, err = client.TransactionsJSAPI(ctx, wx.V3TransactionsJSAPIRequest{ Appid: "wxd678efh567hg6787", Mchid: "1900009191", Description: "Image形象店-深圳腾大-QQ公仔", OutTradeNo: "1217752501201407033233368018", Attach: "自定义数据说明", NotifyUrl: "https://www.weixin.qq.com/wxpay/pay.php", Amount: wx.V3TransactionsJSAPIRequestAmount{ Total: 100, }, Payer: wx.V3TransactionsJSAPIRequestPayer{ Openid: "oUpF8uMuAJO_M2pxb1Q9zNjWeS6o", }, }); err != nil { return } if apiError != nil { log.Print("接口错误:\n", apiError.Error()) log.Print("http:\n", httpResult.DumpRequestResponseString(true)) return apiError } var id string = resp.PrepayId log.Print(id) return }(context.Background()) log.Printf("%+v", err)
Output:
func (V3PayClient) TransferBatches ¶
func (dep V3PayClient) TransferBatches(ctx context.Context, req V3TransferBatchesRequest) ( reply V3TransferBatchesReply, httpResult xhttp.HttpResult, apiError *V3PayApiError, err error, )
TransferBatches https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_1.shtml 商户可以通过该接口同时向多个用户微信零钱进行转账操作。
Example ¶
err := func(ctx context.Context) (err error) { var client *wx.V3PayClient if client, err = NewV3PayClient(); err != nil { return } var apiError *wx.V3PayApiError var httpResult xhttp.HttpResult var resp wx.V3TransferBatchesReply if resp, httpResult, apiError, err = client.TransferBatches(ctx, wx.V3TransferBatchesRequest{ Appid: "wxf636efh567hg4356", OutBatchNo: "plfk2020042013", BatchName: "2019年1月深圳分部报销单", BatchRemark: "2019年1月深圳分部报销单", TotalAmount: 4000000, TotalNum: 200, TransferDetailList: []wx.V3TransferBatchesRequestDetail{{ OutDetailNo: "x23zy545Bd5436", TransferAmount: 200000, TransferRemark: "2020年4月报销", Openid: "o-MYE42l80oelYMDE34nYD456Xoy", UserName: "757b340b45ebef5467rter35gf464344v3542sdf4t6re4tb4f54ty45t4yyry45", }}, TransferSceneId: "1000", }); err != nil { return } if apiError != nil { log.Print("接口错误:\n", apiError.Error()) log.Print("http:\n", httpResult.DumpRequestResponseString(true)) return apiError } var id string = resp.BatchId log.Print(id) return }(context.Background()) log.Printf("%+v", err)
Output:
func (V3PayClient) V3H5Pay ¶
func (dep V3PayClient) V3H5Pay(ctx context.Context, req h5.PrepayRequest) (reply *h5.PrepayResponse, httpResult xhttp.HttpResult, apiError *V3PayApiError, err error)
V3H5Pay https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_3_1.shtml
type V3PayConfig ¶
type V3PayConfig struct { APIClientKey *rsa.PrivateKey `eg:"utils.LoadPrivateKeyWithPath(\"apiclient_key.pem\")"` MCHID string `eg:"152000000"` CertificateSerialNumber string `eg:"C731E2BFB6B3204E5B6B46F2044F5F7547BBEE47"` APIV3Key string `eg:"198bbc12f72649a99ac31bd5163a4c93"` }
type V3RefundsRequest ¶
type V3TransactionsJSAPIReply ¶
type V3TransactionsJSAPIReply struct { // 预支付交易会话标识 PrepayId string `json:"prepay_id"` // 应用ID Appid string `json:"appId"` // 时间戳 TimeStamp string `json:"timeStamp"` // 随机字符串 NonceStr string `json:"nonceStr"` // 订单详情扩展字符串 Package string `json:"package"` // 签名方式 SignType string `json:"signType"` // 签名 PaySign string `json:"paySign"` }
type V3TransactionsJSAPIRequest ¶
type V3TransactionsJSAPIRequest struct { Appid string Mchid string Description string OutTradeNo string Attach string NotifyUrl string Amount V3TransactionsJSAPIRequestAmount Payer V3TransactionsJSAPIRequestPayer }
type V3TransactionsJSAPIRequestPayer ¶
type V3TransactionsJSAPIRequestPayer struct {
Openid string
}
type V3TransferBatchesReply ¶
type V3TransferBatchesReply struct { // 商户系统内部的商家批次单号,在商户系统内部唯一 OutBatchNo string // 微信批次单号,微信商家转账系统返回的唯一标识 BatchId string // 批次受理成功时返回,按照使用rfc3339所定义的格式,格式为YYYY-MM-DDThh:mm:ss+TIMEZONE CreateTime time.Time // ACCEPTED:已受理。批次已受理成功,若发起批量转账的30分钟后,转账批次单仍处于该状态,可能原因是商户账户余额不足等。商户可查询账户资金流水,若该笔转账批次单的扣款已经发生,则表示批次已经进入转账中,请再次查单确认 PROCESSING:转账中。已开始处理批次内的转账明细单 FINISHED:已完成。批次内的所有转账明细单都已处理完成 CLOSED:已关闭。可查询具体的批次关闭原因确认 BatchStatus string }
type V3TransferBatchesRequest ¶
type V3TransferBatchesRequest struct { // 申请商户号的appid或商户号绑定的appid(企业号corpid即为此appid) Appid string // 商户系统内部的商家批次单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一 OutBatchNo string // 该笔批量转账的名称 BatchName string // 转账说明,UTF8编码,最多允许32个字符 BatchRemark string // 转账金额单位为“分”。转账总金额必须与批次内所有明细转账金额之和保持一致,否则无法发起转账操作 TotalAmount int64 // 一个转账批次单最多发起一千笔转账。转账总笔数必须与批次内所有明细之和保持一致,否则无法发起转账操作 TotalNum int64 // 发起批量转账的明细列表,最多一千笔 TransferDetailList []V3TransferBatchesRequestDetail // 该批次转账使用的转账场景,如不填写则使用商家的默认场景,如无默认场景可为空,可前往“商家转账到零钱-前往功能”中申请。 如:1001-现金营销 TransferSceneId string }
func (V3TransferBatchesRequest) WechatSDK ¶
func (v V3TransferBatchesRequest) WechatSDK() transferbatch.InitiateBatchTransferRequest
type V3TransferBatchesRequestDetail ¶
type V3TransferBatchesRequestDetail struct { // 商户系统内部区分转账批次单下不同转账明细单的唯一标识,要求此参数只能由数字、大小写字母组成 OutDetailNo string // 转账金额单位为“分” TransferAmount int64 // 单条转账备注(微信用户会收到该备注),UTF8编码,最多允许32个字符 TransferRemark string // 商户appid下,某用户的openid Openid string // 收款方真实姓名。支持标准RSA算法和国密算法,公钥由微信侧提供 明细转账金额<0.3元时,不允许填写收款用户姓名 明细转账金额 >= 2,000元时,该笔明细必须填写收款用户姓名 同一批次转账明细中的姓名字段传入规则需保持一致,也即全部填写、或全部不填写 若商户传入收款用户姓名,微信支付会校验用户openID与姓名是否一致,并提供电子回单 UserName string }
TransferDetailInput
func (V3TransferBatchesRequestDetail) WechatSDK ¶
func (v V3TransferBatchesRequestDetail) WechatSDK() transferbatch.TransferDetailInput