package wx import ( "encoding/xml" "errors" "fmt" "git.qianqiusoft.com/qianqiusoft/light-apiengine/entitys" "git.qianqiusoft.com/qianqiusoft/light-apiengine/models" "git.qianqiusoft.com/qianqiusoft/light-apiengine/utils" "github.com/silenceper/wechat/js" "github.com/silenceper/wechat/oauth" "github.com/silenceper/wechat/pay" "github.com/silenceper/wechat/util" "io" "io/ioutil" "net/http" "net/url" "os" "strconv" "strings" ) // 微信回调处理器 var _wxPayCallbackHandler func(result *pay.NotifyResult)models.SysReturn = nil // 微信通用登录回调处理器 var _wxLoginCallbackHandler func(ctx *entitys.CtrlContext, body []byte, info *oauth.UserInfo)models.SysReturn = nil // 注册微信支付回调处理函数 func RegisterWxPayCallbackHandler(handler func(result *pay.NotifyResult)models.SysReturn){ _wxPayCallbackHandler = handler } // 调用微信支付回调处理函数 func CallWxPayCallbackHandler(c *entitys.CtrlContext)models.SysReturn{ if _wxPayCallbackHandler == nil{ return models.SysReturn{500, "微信支付回调处理函数为空", nil} } data, err := ioutil.ReadAll(c.Ctx.Request.Body) if err != nil{ fmt.Println("******************----》微信支付回调read request body错误", err.Error()) return models.SysReturn{500, err.Error(), nil} } notifyRet := pay.NotifyResult{} err = xml.Unmarshal(data, ¬ifyRet) //err = c.Ctx.BindXML(¬ifyRet) if err != nil{ fmt.Println("******************----》微信支付回调bindxml错误", err.Error()) return models.SysReturn{500, err.Error(), nil} } if notifyRet.ResultCode == "SUCCESS" && notifyRet.ReturnCode == "SUCCESS"{ ok, err := VerifyResponseData(data, wxConfig.PayKey) if err != nil{ fmt.Println("*****************---->微信支付回调验证错误", err.Error()) return models.SysReturn{500, err.Error(), nil} } if !ok{ fmt.Println("*****************---->微信支付回调验证错误, ok is false") return models.SysReturn{500, "", nil} } return _wxPayCallbackHandler(¬ifyRet) }else{ fmt.Println("------------------>微信支付失败", notifyRet) return models.SysReturn{500, "", ""} } } // 注册微信登录回调处理函数 func RegisterWxLoginCallbackHandler(handler func(ctx *entitys.CtrlContext, body []byte, info *oauth.UserInfo)models.SysReturn){ _wxLoginCallbackHandler = handler } // 调用微信登录处理函数 func CallWxLoginCallbackHandler(ctx *entitys.CtrlContext, body []byte, info *oauth.UserInfo)models.SysReturn{ if _wxLoginCallbackHandler == nil{ return models.SysReturn{500, "微信登录回调处理函数为空", nil} }else{ return _wxLoginCallbackHandler(ctx, body, info) } } // 扫码支付 func PayNative(params *PayParams)(*pay.PayResult, error){ ip := utils.GetIP(params.Ctx) attach := params.Attach if attach == ""{ attach = params.Ctx.Ctx.GetString("user_id") if attach == ""{ attach = "attach" } } body := params.Body if body == ""{ body = "body" } if params.OutTradeNo == ""{ return nil, errors.New("交易单号为空") } parParams := pay.Params{strconv.Itoa(params.TotalFee), ip, body, attach, params.OutTradeNo, ""} return wc.GetPay().PreNative(&parParams) } // jsapi 支付 func PayJSAPI(params *PayParams)(*JSAPIPayConfig, error){ openId := params.OpenId if openId == ""{ return nil, errors.New("openid 为空") } if params.OutTradeNo == ""{ return nil, errors.New("交易单号为空") } attach := params.Attach if attach == ""{ fmt.Println("--------------------->1") attach = params.Ctx.Ctx.GetString("user_id") if attach == ""{ fmt.Println("--------------------->2") attach = "attach" } } body := params.Body if body == ""{ body = "body" } ip := utils.GetIP(params.Ctx) fmt.Println("params.Attach", params.Attach, "attach", attach) payParams := pay.Params{ strconv.Itoa(params.TotalFee), ip, body, attach, params.OutTradeNo, params.OpenId, } payObj := wc.GetPay() prePayID, err := payObj.PrePayID(&payParams) if err != nil{ fmt.Println("----------------->prepayid error", err.Error()) return nil, err } nonceStr := util.RandomStr(32) timestamp := util.GetCurrTs() pack := "prepay_id=" + prePayID template := "appId=%s&nonceStr=%s&package=%s&signType=MD5&timeStamp=%s&key=%s" str := fmt.Sprintf(template, payObj.AppID, nonceStr, pack, strconv.FormatInt(timestamp, 10), payObj.PayKey) sign := util.MD5Sum(str) payCfg := pay.Config{timestamp, nonceStr, prePayID, "MD5", sign} exPayConfig := JSAPIPayConfig{} exPayConfig.AppId = wxConfig.AppId exPayConfig.NonceStr = payCfg.NonceStr exPayConfig.OutTradeNo = params.OutTradeNo exPayConfig.Package = "prepay_id=" + payCfg.PrePayID exPayConfig.PaySign = payCfg.Sign exPayConfig.SignType = payCfg.SignType exPayConfig.Timestamp = strconv.Itoa(int(payCfg.Timestamp)) if err==nil { return &exPayConfig, nil }else{ return nil, err } } // 关闭订单 func CloseOrder(outTradeNo string)(*pay.CloseOrderResult, error){ return wc.GetPay().CloseOrder(outTradeNo) } // 获取微信OAuth认证参数 func GetOAuthParams(paramMap map[string]string)(*WxOAuthConfig, error){ config := WxOAuthConfig{} urlstr := wxConfig.RedirectUrl paramstr := "" for k, v := range paramMap{ paramstr += fmt.Sprintf("%s=%s", k, url.QueryEscape(v)) } if strings.Index(urlstr, "%s") > 0{ urlstr = fmt.Sprintf(urlstr, paramstr) } url, err := wxoauth.GetRedirectURL(urlstr, wxConfig.Scope, url.QueryEscape(wxConfig.State)) if err != nil{ return nil, err } config.OAuthRedirectUrl = url config.AppId = wxConfig.AppId config.State = wxConfig.State config.Scope = wxConfig.Scope config.ResponseType = wxConfig.ResponseType config.AuthUrl = "https://open.weixin.qq.com/connect/oauth2/authorize" config.RedirectUrl = wxConfig.RedirectUrl return &config, nil } // 获取jssdk配置参数 func GetJSSDKRarams(url string)(*js.Config, error){ return wc.GetJs().GetConfig(url) } // 获取token func GetOpenId(code string)(string, error){ resToken, err := wxoauth.GetUserAccessToken(code) if err == nil{ addToken(resToken.OpenID, &resToken) } return resToken.OpenID, err } // 根据code获取用户信息(需scope为 snsapi_userinfo) func GetUserInfoByCode(code string)(*oauth.UserInfo, error){ openId, err := GetOpenId(code) if err != nil{ return nil, err } return GetUserInfo(openId) } // 获取用户信息(需scope为 snsapi_userinfo) func GetUserInfo(openId string)(*oauth.UserInfo, error){ token := getToken(openId) if token == nil{ return nil, errors.New("token of openid " + openId + "does not exist") } userInfo, err := wxoauth.GetUserInfo(token.AccessToken, openId) return &userInfo, err } /** * @brief: 根据资源id从微信下载 * @param1 resId: 资源id * @param2 tagFile: 目标文件 * @return: 错误信息 */ func Download(resId, tagFile string)error{ token, err := wc.GetAccessToken() if err != nil{ fmt.Println("wc.GetAccessToken()错误", err.Error()) return err } mediaUrl := "https://api.weixin.qq.com/cgi-bin/media/get" downloadUrl := mediaUrl + "?access_token=" + token + "&media_id=" + resId res, err := http.Get(downloadUrl) if err != nil{ fmt.Println("请求资源错误:" + err.Error()) return err } f, err := os.Create(tagFile) if err != nil { fmt.Println("本地创建资源文件:" + err.Error()) return err } _, err = io.Copy(f, res.Body) if err != nil{ fmt.Println("写入本地资源文件:" + err.Error()) return err }else{ return nil } }