wx.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. package wx
  2. import (
  3. "encoding/xml"
  4. "errors"
  5. "fmt"
  6. "git.qianqiusoft.com/qianqiusoft/light-apiengine/entitys"
  7. "git.qianqiusoft.com/qianqiusoft/light-apiengine/models"
  8. "git.qianqiusoft.com/qianqiusoft/light-apiengine/utils"
  9. "github.com/silenceper/wechat/js"
  10. "github.com/silenceper/wechat/oauth"
  11. "github.com/silenceper/wechat/pay"
  12. "github.com/silenceper/wechat/util"
  13. "io/ioutil"
  14. "net/url"
  15. "strconv"
  16. "strings"
  17. )
  18. var wxPayCallbackHandler func(result *pay.NotifyResult)models.SysReturn = nil
  19. // 注册微信支付回调处理函数
  20. func RegisterWxPayCallbackHandler(handler func(result *pay.NotifyResult)models.SysReturn){
  21. wxPayCallbackHandler = handler
  22. }
  23. func CallWxPayCallbackHandler(c *entitys.CtrlContext)models.SysReturn{
  24. if wxPayCallbackHandler == nil{
  25. return models.SysReturn{500, "微信支付回调处理函数为空", nil}
  26. }
  27. data, err := ioutil.ReadAll(c.Ctx.Request.Body)
  28. if err != nil{
  29. fmt.Println("******************----》微信支付回调read request body错误", err.Error())
  30. return models.SysReturn{500, err.Error(), nil}
  31. }
  32. notifyRet := pay.NotifyResult{}
  33. err = xml.Unmarshal(data, &notifyRet)
  34. //err = c.Ctx.BindXML(&notifyRet)
  35. if err != nil{
  36. fmt.Println("******************----》微信支付回调bindxml错误", err.Error())
  37. return models.SysReturn{500, err.Error(), nil}
  38. }
  39. if notifyRet.ResultCode == "SUCCESS" && notifyRet.ReturnCode == "SUCCESS"{
  40. ok, err := VerifyResponseData(data, wxConfig.PayKey)
  41. if err != nil{
  42. fmt.Println("*****************---->微信支付回调验证错误", err.Error())
  43. return models.SysReturn{500, err.Error(), nil}
  44. }
  45. if !ok{
  46. fmt.Println("*****************---->微信支付回调验证错误, ok is false")
  47. return models.SysReturn{500, "", nil}
  48. }
  49. return wxPayCallbackHandler(&notifyRet)
  50. }else{
  51. fmt.Println("------------------>微信支付失败", notifyRet)
  52. return models.SysReturn{500, "", ""}
  53. }
  54. }
  55. // 扫码支付
  56. func PayNative(params *PayParams)(*pay.PayResult, error){
  57. ip := utils.GetIP(params.Ctx)
  58. attach := params.Attach
  59. if attach == ""{
  60. attach = params.Ctx.Ctx.GetString("user_id")
  61. if attach == ""{
  62. attach = "attach"
  63. }
  64. }
  65. body := params.Body
  66. if body == ""{
  67. body = "body"
  68. }
  69. if params.OutTradeNo == ""{
  70. return nil, errors.New("交易单号为空")
  71. }
  72. parParams := pay.Params{strconv.Itoa(params.TotalFee), ip, body, attach, params.OutTradeNo, ""}
  73. return wc.GetPay().PreNative(&parParams)
  74. }
  75. // jsapi 支付
  76. func PayJSAPI(params *PayParams)(*JSAPIPayConfig, error){
  77. openId := params.OpenId
  78. if openId == ""{
  79. return nil, errors.New("openid 为空")
  80. }
  81. if params.OutTradeNo == ""{
  82. return nil, errors.New("交易单号为空")
  83. }
  84. attach := params.Attach
  85. if attach == ""{
  86. fmt.Println("--------------------->1")
  87. attach = params.Ctx.Ctx.GetString("user_id")
  88. if attach == ""{
  89. fmt.Println("--------------------->2")
  90. attach = "attach"
  91. }
  92. }
  93. body := params.Body
  94. if body == ""{
  95. body = "body"
  96. }
  97. ip := utils.GetIP(params.Ctx)
  98. fmt.Println("params.Attach", params.Attach, "attach", attach)
  99. payParams := pay.Params{
  100. strconv.Itoa(params.TotalFee),
  101. ip,
  102. body,
  103. attach,
  104. params.OutTradeNo,
  105. params.OpenId,
  106. }
  107. payObj := wc.GetPay()
  108. prePayID, err := payObj.PrePayID(&payParams)
  109. if err != nil{
  110. fmt.Println("----------------->prepayid error", err.Error())
  111. return nil, err
  112. }
  113. nonceStr := util.RandomStr(32)
  114. timestamp := util.GetCurrTs()
  115. pack := "prepay_id=" + prePayID
  116. template := "appId=%s&nonceStr=%s&package=%s&signType=MD5&timeStamp=%s&key=%s"
  117. str := fmt.Sprintf(template, payObj.AppID, nonceStr, pack, strconv.FormatInt(timestamp, 10), payObj.PayKey)
  118. sign := util.MD5Sum(str)
  119. payCfg := pay.Config{timestamp, nonceStr, prePayID, "MD5", sign}
  120. exPayConfig := JSAPIPayConfig{}
  121. exPayConfig.AppId = wxConfig.AppId
  122. exPayConfig.NonceStr = payCfg.NonceStr
  123. exPayConfig.OutTradeNo = params.OutTradeNo
  124. exPayConfig.Package = "prepay_id=" + payCfg.PrePayID
  125. exPayConfig.PaySign = payCfg.Sign
  126. exPayConfig.SignType = payCfg.SignType
  127. exPayConfig.Timestamp = strconv.Itoa(int(payCfg.Timestamp))
  128. if err==nil {
  129. return &exPayConfig, nil
  130. }else{
  131. return nil, err
  132. }
  133. }
  134. // 关闭订单
  135. func CloseOrder(outTradeNo string)(*pay.CloseOrderResult, error){
  136. return wc.GetPay().CloseOrder(outTradeNo)
  137. }
  138. // 获取微信OAuth认证参数
  139. func GetOAuthParams(paramMap map[string]string)(*WxOAuthConfig, error){
  140. config := WxOAuthConfig{}
  141. urlstr := wxConfig.RedirectUrl
  142. paramstr := ""
  143. for k, v := range paramMap{
  144. paramstr += fmt.Sprintf("%s=%s", k, url.QueryEscape(v))
  145. }
  146. if strings.Index(urlstr, "%s") > 0{
  147. urlstr = fmt.Sprintf(urlstr, paramstr)
  148. }
  149. url, err := wxoauth.GetRedirectURL(urlstr, wxConfig.Scope, url.QueryEscape(wxConfig.State))
  150. if err != nil{
  151. return nil, err
  152. }
  153. config.OAuthRedirectUrl = url
  154. config.AppId = wxConfig.AppId
  155. config.State = wxConfig.State
  156. config.Scope = wxConfig.Scope
  157. config.ResponseType = wxConfig.ResponseType
  158. config.AuthUrl = "https://open.weixin.qq.com/connect/oauth2/authorize"
  159. config.RedirectUrl = wxConfig.RedirectUrl
  160. return &config, nil
  161. }
  162. // 获取jssdk配置参数
  163. func GetJSSDKRarams(url string)(*js.Config, error){
  164. return wc.GetJs().GetConfig(url)
  165. }
  166. // 获取token
  167. func GetOpenId(code string)(string, error){
  168. resToken, err := wxoauth.GetUserAccessToken(code)
  169. if err == nil{
  170. addToken(resToken.OpenID, &resToken)
  171. }
  172. return resToken.OpenID, err
  173. }
  174. // 根据code获取用户信息(需scope为 snsapi_userinfo)
  175. func GetUserInfoByCode(code string)(*oauth.UserInfo, error){
  176. openId, err := GetOpenId(code)
  177. if err != nil{
  178. return nil, err
  179. }
  180. return GetUserInfo(openId)
  181. }
  182. // 获取用户信息(需scope为 snsapi_userinfo)
  183. func GetUserInfo(openId string)(*oauth.UserInfo, error){
  184. token := getToken(openId)
  185. if token == nil{
  186. return nil, errors.New("token of openid " + openId + "does not exist")
  187. }
  188. userInfo, err := wxoauth.GetUserInfo(token.AccessToken, openId)
  189. return &userInfo, err
  190. }