123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 |
- package service
- import (
- "errors"
- "fmt"
- "io"
- "sync"
- "time"
- "gopkg.in/redis.v2"
- "xiaoniaokuaiyan.com/xiaoniao/config"
- "xiaoniaokuaiyan.com/xiaoniao/pay/wx"
- "xiaoniaokuaiyan.com/xiaoniao/util"
- )
- type WeixinService struct {
- accessToken *wx.AccessToken
- jsTicket *wx.AccessToken
- wx.Weixin
- wx.JsSdk
- WeixinMp wx.Weixin
- }
- const REDIS_WX_ACCESSTOKEN_KEY = "wx_access_token"
- const REDIS_WX_JSAPI_TICKET_KEY = "wx_jsapi_ticket"
- func (wxSrv *WeixinService) GetWXAccessToken(accountType string) (interface{}, error) {
- var (
- tokenStr string
- err error
- //env string = config.IniConf.Section("server").Key("env").Value()
- suffix string
- weixin wx.Weixin = wxSrv.Weixin
- )
- //if env == "production" {
- if accountType == "mp" {
- suffix = "_mp"
- weixin = wxSrv.WeixinMp
- }
- tokenStr, err = getWxRedisValue(REDIS_WX_ACCESSTOKEN_KEY + suffix)
- //} else {
- // tokenStr, err = util.GetRedisValue(REDIS_WX_ACCESSTOKEN_KEY)
- //}
- if err != nil || tokenStr == "" {
- tokenRes, err := weixin.GetAccessToken()
- if err != nil {
- return nil, err
- }
- //if env == "production" {
- setWxRedisValue(REDIS_WX_ACCESSTOKEN_KEY+suffix, tokenRes.AccessToken, int64(time.Second)*(tokenRes.ExpiresIn-5))
- //} else {
- // util.SetRedisValue(REDIS_WX_ACCESSTOKEN_KEY, tokenRes.AccessToken, int64(time.Second)*(tokenRes.ExpiresIn-5))
- //}
- return tokenRes.AccessToken, nil
- }
- return tokenStr, nil
- }
- func (wxSrv *WeixinService) GetJSAPITicket(accountType string) (interface{}, error) {
- var (
- ticketStr string
- err error
- // env string = config.IniConf.Section("server").Key("env").Value()
- suffix string
- )
- if accountType == "mp" {
- suffix = "_mp"
- }
- //if env == "production" {
- ticketStr, err = getWxRedisValue(REDIS_WX_JSAPI_TICKET_KEY)
- //} else {
- // ticketStr, err = util.GetRedisValue(REDIS_WX_JSAPI_TICKET_KEY)
- //}
- if err != nil || ticketStr == "" {
- token, err := wxSrv.GetWXAccessToken(accountType)
- if err != nil {
- return nil, err
- }
- ticketRes, err := wxSrv.JsSdk.GetTicket(token.(string))
- if err != nil {
- return nil, err
- }
- //if env == "production" {
- setWxRedisValue(REDIS_WX_JSAPI_TICKET_KEY+suffix, ticketRes.Ticket, int64(time.Second)*(ticketRes.ExpiresIn-5))
- //} else {
- // util.SetRedisValue(REDIS_WX_JSAPI_TICKET_KEY, ticketRes.Ticket, int64(time.Second)*(ticketRes.ExpiresIn-5))
- //}
- return ticketRes.Ticket, nil
- }
- return ticketStr, nil
- }
- func (wxSrv *WeixinService) JsSdkSign(signUrl string, accountType string) (interface{}, error) {
- accessToken, err := wxSrv.GetWXAccessToken(accountType)
- if err != nil {
- return nil, err
- }
- ticket, err := wxSrv.GetJSAPITicket(accountType)
- if err != nil {
- return nil, err
- }
- spkg, err := wxSrv.JsSdk.ComputeSignature(accessToken.(string), ticket.(string), signUrl)
- if err != nil {
- return nil, err
- }
- delete(spkg, "access_token")
- delete(spkg, "ticket")
- if accountType == "mp" {
- spkg["appid"] = config.IniConf.Section("weixin").Key("wx.mp.appid").Value()
- } else {
- spkg["appid"] = config.IniConf.Section("weixin").Key("wx.appid").Value()
- }
- return spkg, nil
- }
- func (wxSrv *WeixinService) Send(msg map[string]interface{}, accountType string) (interface{}, error) {
- token, err := wxSrv.GetWXAccessToken(accountType)
- if err != nil {
- return nil, err
- }
- err = wxSrv.Weixin.Send(msg, token.(string))
- if err != nil {
- return false, err
- }
- return true, nil
- }
- func (wxSrv *WeixinService) SendTpl(msg string, accountType string) (interface{}, error) {
- token, err := wxSrv.GetWXAccessToken(accountType)
- if err != nil {
- return nil, err
- }
- err = wxSrv.Weixin.SendTpl(msg, token.(string), accountType)
- if err != nil {
- return false, err
- }
- return true, nil
- }
- func (wxSrv *WeixinService) ScanPay(extra map[string]string) (interface{}, error) {
- if _, ok := extra["ip"]; !ok {
- return nil, errors.New("need request ip")
- }
- if _, ok := extra["trade_type"]; !ok {
- return nil, errors.New("need param trade_type of weixin pay")
- }
- if _, ok := extra["device_info"]; !ok && extra["trade_type"] == "JSAPI" {
- extra["device_info"] = "WEB"
- }
- if _, ok := extra["openid"]; !ok && extra["trade_type"] == "JSAPI" {
- return nil, errors.New("miss param openid")
- }
- if _, ok := extra["usefor"]; !ok || extra["usefor"] == "" {
- return nil, errors.New("param usefor must not equal empty")
- }
- var remark interface{} = nil
- if _, ok := extra["remark"]; ok {
- remark = extra["remark"]
- }
- payNo := GenerateOrderPayNO("SP")
- wxJsSdk := wx.NewJsSdk()
- var (
- appid string = wx.DefaultConfig["appid"]
- secret = wx.DefaultConfig["secret"]
- )
- if extra["wx_type"] == "mp" {
- appid = config.IniConf.Section("weixin").Key("wx.mp.appid").Value()
- secret = config.IniConf.Section("weixin").Key("wx.mp.secret").Value()
- }
- weixin := wx.NewWeixin(appid, secret)
- nonceStr := wxJsSdk.GenerateNoncestr(16)
- reqItem := map[string]string{
- "appid": appid,
- "mch_id": wx.DefaultConfig["mch_id"],
- "nonce_str": nonceStr,
- "body": "小鸟快验订单-" + payNo,
- "notify_url": config.IniConf.Section("weixin").Key("wx.scanpaycb_notify_url").Value(),
- "out_trade_no": payNo,
- "spbill_create_ip": extra["ip"],
- "total_fee": extra["total_fee"],
- "trade_type": extra["trade_type"],
- }
- if extra["trade_type"] == "JSAPI" {
- reqItem["openid"] = extra["openid"]
- }
- if extra["device_info"] != "" {
- reqItem["device_info"] = extra["device_info"]
- }
- sign := wxJsSdk.ComputePaySignature(reqItem, wx.DefaultConfig["apikey"])
- reqItem["sign"] = sign
- rel, err := weixin.PrepareOrder(reqItem)
- if err != nil {
- return nil, err
- }
- if rel.ReturnCode == "FAIL" {
- return nil, errors.New(rel.ReturnMsg)
- }
- db := util.GetWriteSqlDB()
- sqlResult := db.MustExec("insert into t_custom_wxscan_pay(id, openid, payment, usefor, remark) values(?,?,?,?,?)", payNo, extra["openid"], extra["total_fee"], extra["usefor"], remark)
- if re, _ := sqlResult.RowsAffected(); re <= 0 {
- return nil, errors.New("failed to save data")
- }
- resultItem := map[string]string{
- "appId": appid,
- "timeStamp": fmt.Sprintf("%d", time.Now().Unix()),
- "nonceStr": wxJsSdk.GenerateNoncestr(16),
- "package": "prepay_id=" + rel.PrepayId,
- "signType": "MD5",
- "mweb_url": rel.MWebUrl,
- "code_url": rel.CodeUrl,
- }
- resultItem["sign"] = wxJsSdk.ComputePaySignature(resultItem, config.IniConf.Section("weixin").Key("wx.apikey").Value())
- resultItem["pay_id"] = payNo
- return resultItem, nil
- }
- func (wxSrv *WeixinService) GetPayReason() (interface{}, error) {
- db := util.GetSqlDB()
- var reasonList = []string{}
- err := db.Select(&reasonList, "select usefor from t_custom_pay_usefor where status = 0;")
- if err != nil {
- return nil, err
- }
- return reasonList, nil
- }
- /*func (wxSrv *WeixinService) GetWXAccessToken() (interface{}, error) {
- //todo cache to redis
- if wxSrv.accessToken != nil && !wxSrv.accessToken.IsExpired() {
- return wxSrv.accessToken.TokenStr, nil
- }
- tokenRes, err := wxSrv.Weixin.GetAccessToken()
- if err != nil {
- return nil, err
- }
- wxSrv.accessToken = &wx.AccessToken{
- TokenStr: tokenRes.AccessToken,
- ExpiresAt: time.Now().Unix() + tokenRes.ExpiresIn,
- }
- return wxSrv.accessToken.TokenStr, nil
- }
- func (wxSrv *WeixinService) GetJSAPITicket() (interface{}, error) {
- if wxSrv.jsTicket != nil && !wxSrv.jsTicket.IsExpired() {
- return wxSrv.jsTicket.TokenStr, nil
- }
- token, err := wxSrv.GetWXAccessToken()
- if err != nil {
- return nil, err
- }
- ticketRes, err := wxSrv.JsSdk.GetTicket(token.(string))
- if err != nil {
- return nil, err
- }
- wxSrv.jsTicket = &wx.AccessToken{
- TokenStr: ticketRes.Ticket,
- ExpiresAt: time.Now().Unix() + ticketRes.ExpiresIn,
- }
- return wxSrv.jsTicket.TokenStr, nil
- }
- */
- var wxredisInstance *redis.Client
- var wxredisOnce sync.Once
- func getWxRedis() *redis.Client {
- wxredisOnce.Do(func() {
- var redisOptions *redis.Options = &redis.Options{
- Addr: "101.201.196.166:6379",
- }
- wxredisInstance = redis.NewTCPClient(redisOptions)
- })
- cmdStatus := wxredisInstance.Auth("xn9659$")
- if cmdStatus.Err() == io.EOF {
- wxredisInstance.Ping()
- wxredisInstance.Auth("xn9659$")
- }
- return wxredisInstance
- }
- func getWxRedisValue(key string) (string, error) {
- client := getWxRedis()
- client.Select(12)
- strCmd := client.Get(key)
- if err := strCmd.Err(); err != nil {
- return "", err
- }
- return strCmd.Val(), nil
- }
- func setWxRedisValue(key, val string, period int64) (bool, error) {
- client := getWxRedis()
- client.Select(12)
- statusCmd := client.Set(key, val)
- if err := statusCmd.Err(); err != nil {
- return false, err
- }
- if int64(period) > 0 {
- client.Expire(key, time.Duration(period))
- }
- return true, nil
- }
|