123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- package platformPay
- import (
- "errors"
- "fmt"
- "github.com/sirupsen/logrus"
- "leafstalk/log"
- "net/http"
- "sort"
- "strconv"
- "strings"
- "time"
- )
- var (
- dyAccessToken string
- dyAccessTokenExpires int64
- DyAppId = "tt657f13c2fa40ef9802"
- DYBalanceUri = "/api/apps/game/wallet/get_balance"
- DYpayUri = "/api/apps/game/wallet/game_pay"
- DyPaySecret = "8a25288267fa81f75581b5018378cb0e"
- )
- // 从中台获取抖音支付TOKEN
- // 抖音查询余额签名函数
- func DyMakeQueryBalanceSig(md map[string]interface{}, uri string) string {
- var str string
- var ms []string
- for k, v := range md {
- switch v := v.(type) {
- case string:
- str = k + "=" + v
- ms = append(ms, str)
- case int:
- str = k + "=" + strconv.FormatInt(int64(v), 10)
- ms = append(ms, str)
- case int64:
- str = k + "=" + strconv.FormatInt(v, 10)
- ms = append(ms, str)
- }
- }
- sort.Strings(ms)
- str = "org_loc=" + uri
- ms = append(ms, str)
- str = "method=POST"
- ms = append(ms, str)
- var nstr string = strings.Join(ms, "&")
- r := hmacSha256(nstr, DyPaySecret)
- return r
- }
- // 查询余额接口
- func DyQueryBalance(openid string) (*ResponseGetBalance, error) {
- req := NewHttpRequest()
- requestData := make(map[string]interface{})
- requestData["openid"] = openid //"oNEBv5CU3aOz7FcWp5ZDlhCNc3-U"
- requestData["appid"] = DyAppId //"wx831355257c862ac2"
- // requestData["offer_id"] = offerId //"1450030892"
- requestData["ts"] = time.Now().Unix()
- requestData["zone_id"] = "1"
- requestData["pf"] = "android"
- requestData["access_token"] = dyAccessToken //dyAccessToken
- requestData["mp_sig"] = DyMakeQueryBalanceSig(requestData, DYBalanceUri) //(requestData, getBalanceUri)
- // https://developer.toutiao.com/api/apps/game/wallet/get_balance
- url := "https://developer.toutiao.com" + DYBalanceUri
- resp, err := req.JSON(requestData).Post(url)
- if err != nil {
- //log.Warnln(err)
- return nil, err
- }
- defer func() {
- if resp.GetBody() != nil {
- resp.GetBody().Close()
- }
- }()
- if resp.GetStatusCode() != http.StatusOK {
- return nil, errors.New(fmt.Sprintf("请求余额失败:%v", resp.GetStatusCode()))
- }
- res := new(ResponseGetBalance)
- err = resp.UnmarshalBody(res)
- if err != nil {
- return nil, err
- }
- if res.ErrCode != 0 {
- return nil, errors.New(res.ErrMsg)
- }
- return res, nil
- }
- func DyQueryBalanceAndCheck(openid string) (*ResponseGetBalance, error) {
- // token不存在或过期则去请求
- if len(dyAccessToken) == 0 || time.Now().Unix() > dyAccessTokenExpires-60 {
- token, expired, err := QueryAccessToken(int(DyPlat), dyAccessTokenExpires)
- if err == nil {
- dyAccessToken = token
- dyAccessTokenExpires = expired
- }
- }
- rgb, err := DyQueryBalance(openid)
- if err != nil {
- return rgb, err
- }
- // 繁忙再请求
- if rgb.ErrCode == -1 {
- rgb, err = DyQueryBalance(openid)
- }
- // token失效再请求
- if rgb.ErrCode == 90017 || rgb.ErrCode == 90018 { // rgb.ErrCode == 40001 || rgb.ErrCode == 41001 ||
- token, expired, err := QueryAccessToken(int(DyPlat), dyAccessTokenExpires)
- if err == nil {
- dyAccessToken = token
- dyAccessTokenExpires = expired
- return DyQueryBalance(openid)
- }
- }
- return rgb, err
- }
- // 扣除余额接口
- func DyPay(openid string, billNo string, amt int) (*ResponsePay, error) {
- req := NewHttpRequest()
- requestData := make(map[string]interface{})
- requestData["openid"] = openid //"oNEBv5CU3aOz7FcWp5ZDlhCNc3-U"
- requestData["appid"] = DyAppId //"wx831355257c862ac2"
- // requestData["offer_id"] = offerId //"1450030892"
- requestData["ts"] = time.Now().Unix()
- requestData["zone_id"] = "1"
- requestData["pf"] = "android"
- requestData["amt"] = amt
- requestData["bill_no"] = billNo
- //requestData["pay_item"] = "钻石"
- requestData["access_token"] = dyAccessToken
- requestData["mp_sig"] = DyMakeQueryBalanceSig(requestData, DYpayUri)
- // https://developer.toutiao.com/api/apps/game/wallet/game_pay
- url := "https://developer.toutiao.com" + DYpayUri
- logrus.Infof("DyPay params: %+v", requestData)
- resp, err := req.JSON(requestData).Post(url)
- if err != nil {
- //log.Warnln(err)
- return nil, err
- }
- defer func() {
- if resp.GetBody() != nil {
- resp.GetBody().Close()
- }
- }()
- if resp.GetStatusCode() == 200 {
- res := new(ResponsePay)
- resp.UnmarshalBody(res)
- //log.Warnf("%#v", res)
- return res, nil
- }
- return nil, nil
- }
- func DyPayAndCheck(openid string, billNo string, amt int) (*ResponsePay, error) {
- var rp *ResponsePay
- var err error
- for i := 0; i < 3; i++ {
- rp, err = DyPay(openid, billNo, amt)
- if err != nil {
- log.Warnf("DyPayAndCheck error: %v", err)
- time.Sleep(time.Millisecond * 10)
- continue
- }
- if rp.ErrCode == 0 {
- return rp, err
- }
- if rp.ErrCode == -1 {
- continue
- }
- if rp.ErrCode == 90017 || rp.ErrCode == 90018 {
- token, expired, err := QueryAccessToken(int(DyPlat), dyAccessTokenExpires)
- if err != nil {
- return rp, err
- }
- dyAccessToken = token
- dyAccessTokenExpires = expired
- continue
- }
- if rp.ErrCode < 0 {
- time.Sleep(time.Millisecond * 10)
- continue
- }
- return rp, err
- }
- return rp, err
- }
- // // 有效期2小时,定时刷新,提前刷新,会导致前一个token有效期变为5分钟;
- // func QueryDouYinAccessToken() error {
- // req := NewHttpRequest()
- // requestData := make(map[string]string)
- // requestData["grant_type"] = "client_credential"
- // requestData["appid"] = service.appId
- // requestData["secret"] = service.appSecret
- // resp, err := req.Query(requestData).Get(config.AppConfig.WxRefreshTokenUrl)
- // logrus.Info("query params:", requestData)
- // if err != nil {
- // //log.Warnln(err)
- // return err
- // }
- // defer func() {
- // if resp.GetBody() != nil {
- // resp.GetBody().Close()
- // }
- // }()
- // if resp.GetStatusCode() == 200 {
- // rt := new(ResponseAccessToken)
- // err := resp.UnmarshalBody(rt)
- // if err != nil {
- // logrus.Warnln("parse AccessToken err:", err.Error())
- // return err
- // }
- // if rt.ErrCode == 0 {
- // AccessToken := rt.AccessToken
- // //失效时间缩短一分钟
- // AccessTokenExpiredAt := time.Now().Add(time.Second * time.Duration(rt.ExpiresIn-60)).Unix()
- // service.UpdateAccessToken(AccessToken, AccessTokenExpiredAt)
- // atomic.StoreInt32(&service.ExpiredReportCount, 0)
- // }
- // logrus.Info("query resp:", rt)
- // } else {
- // logrus.Info("query resp code:", resp.GetStatusCode())
- // body, err := resp.GetBodyAsString()
- // logrus.Info("query resp body:", body)
- // logrus.Info("query resp err:", err.Error())
- // }
- // return nil, nil
- // }
|