123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- package platformPay
- import (
- "crypto/hmac"
- "crypto/sha256"
- "encoding/hex"
- "fmt"
- "github.com/sirupsen/logrus"
- "leafstalk/log"
- "os"
- "sort"
- "strconv"
- "strings"
- "time"
- )
- var (
- //appId string
- //appSecret string
- //
- //offerId string
- //midasSecret string
- //
- wxAccessToken string
- wxAccessTokenExpires = time.Now().Unix()
- getBalanceUri = "/cgi-bin/midas/getbalance"
- payUri = "/cgi-bin/midas/pay"
- cancelPayUri = "/cgi-bin/midas/cancelpay"
- presentUri = "/cgi-bin/midas/present"
- )
- func CreateOutTradeNo(id int64) string {
- n := time.Now().Unix()
- return fmt.Sprintf("%v%vS%vU%d", time.Now().Format("20060102150405"), 999, id, n%65536)
- }
- func hmacSha256(msg string, secret string) string {
- k := []byte(secret)
- h := hmac.New(sha256.New, k)
- h.Write([]byte(msg))
- sha := hex.EncodeToString(h.Sum(nil))
- return sha
- //base64.StdEncoding.EncodeToString([]byte(sha))
- }
- func MakeGetBalanceSig(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)
- str = "secret=" + os.Getenv("WXPAY_MIDASSECRET")
- ms = append(ms, str)
- var nstr string = strings.Join(ms, "&")
- r := hmacSha256(nstr, os.Getenv("WXPAY_MIDASSECRET"))
- return r
- }
- //SIG
- //requestData := make(map[string]interface{})
- // requestData["openid"] = "odkx20ENSNa2w5y3g_qOkOvBNM1g"
- // requestData["appid"] = "wx1234567"
- // requestData["offer_id"] = "12345678"
- // requestData["ts"] = int64(1507530737)
- // requestData["zone_id"] = "1"
- // requestData["pf"] = "android"
- // midasSecret = "zNLgAGgqsEWJOg1nFVaO5r7fAlIQxr1u"
- //result: "1ad64e8dcb2ec1dc486b7fdf01f4a15159fc623dc3422470e51cf6870734726b"
- func GetAccessToken(platform int) string {
- if platform == int(WxPlat) {
- return wxAccessToken
- } else {
- return dyAccessToken
- }
- }
- type ResponseGetBalance struct {
- ErrCode int `json:"errcode"`
- ErrMsg string `json:"errmsg"`
- Balance int `json:"balance"` //游戏币个数(包含赠送)
- GenBalance int `json:"gen_balance"` //赠送游戏币数量(赠送游戏币数量)
- FirstSave int `json:"first_save"` //是否满足历史首次充值
- SaveAmt int `json:"save_amt"` //累计充值金额的游戏币数量
- SaveSum int `json:"save_sum"` //历史总游戏币金额
- CostSum int `json:"cost_sum"` //历史总消费游戏币金额
- PresentSum int `json:"present_sum"` //历史累计收到赠送金额
- }
- // 查询余额
- func WxQueryBalance(openid string) (*ResponseGetBalance, error) {
- req := NewHttpRequest()
- requestData := make(map[string]interface{})
- requestData["openid"] = openid //"oNEBv5CU3aOz7FcWp5ZDlhCNc3-U"
- requestData["appid"] = os.Getenv("WXPAY_APPID") //"wx831355257c862ac2"
- requestData["offer_id"] = os.Getenv("WXPAY_OFFERID") //"1450030892"
- requestData["ts"] = time.Now().Unix()
- requestData["zone_id"] = "1"
- requestData["pf"] = "android"
- requestData["sig"] = MakeGetBalanceSig(requestData, getBalanceUri)
- requestData["access_token "] = wxAccessToken
- url := "https://api.weixin.qq.com" + getBalanceUri + "?access_token=" + wxAccessToken
- logrus.Warnf("url:%+v, requestData%+v", url, 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(ResponseGetBalance)
- err := resp.UnmarshalBody(res)
- if err != nil {
- return nil, err
- }
- //log.Warnf("%#v", res)
- return res, nil
- }
- logrus.Warnf("resp.GetStatusCode():%v", resp.GetStatusCode())
- return nil, nil
- }
- func WxQueryBalanceAndCheck(openid string) (*ResponseGetBalance, error) {
- rgb, err := WxQueryBalance(openid)
- if err != nil {
- return rgb, err
- }
- if rgb.ErrCode == 40001 || rgb.ErrCode == 41001 || rgb.ErrCode == 42001 {
- token, expired, err := QueryAccessToken(int(WxPlat), wxAccessTokenExpires)
- if err == nil {
- wxAccessToken = token
- wxAccessTokenExpires = expired
- return WxQueryBalance(openid)
- }
- }
- return rgb, err
- }
- type ResponsePay struct {
- ErrCode int `json:"errcode"`
- ErrMsg string `json:"errmsg"`
- BillNo string `json:"bill_no"`
- Balance int `json:"balance"` //预扣后的余额
- UsedGenAmt int `json:"used_gen_amt"` //本次扣的赠送币的金额
- }
- // 支付
- func WxPay(openid string, billNo string, amt int) (*ResponsePay, error) {
- req := NewHttpRequest()
- requestData := make(map[string]interface{})
- requestData["openid"] = openid //"oNEBv5CU3aOz7FcWp5ZDlhCNc3-U"
- requestData["appid"] = os.Getenv("WXPAY_APPID") //"wx831355257c862ac2"
- requestData["offer_id"] = os.Getenv("WXPAY_OFFERID") //"1450030892"
- requestData["ts"] = time.Now().Unix()
- requestData["zone_id"] = "1"
- requestData["pf"] = "android"
- requestData["amt"] = amt //123
- requestData["bill_no"] = billNo
- //requestData["pay_item"] = "钻石"
- requestData["sig"] = MakeGetBalanceSig(requestData, payUri)
- requestData["access_token "] = wxAccessToken
- url := "https://api.weixin.qq.com" + payUri + "?access_token=" + wxAccessToken
- //url := "https://api.weixin.qq.com/cgi-bin/midas/sandbox/pay?access_token=" + accessToken
- 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)
- err := resp.UnmarshalBody(res)
- if err != nil {
- return nil, err
- }
- //log.Warnf("%#v", res)
- return res, nil
- }
- return nil, nil
- }
- func WxPayAndCheck(openid string, billNo string, amt int) (*ResponsePay, error) {
- var rp *ResponsePay
- var err error
- for i := 0; i < 3; i++ {
- rp, err = WxPay(openid, billNo, amt)
- if err != nil {
- log.Warnf("PayAndCheck error: %v", err)
- time.Sleep(time.Millisecond * 10)
- continue
- }
- if rp.ErrCode == 0 {
- return rp, err
- }
- if rp.ErrCode == 40001 || rp.ErrCode == 41001 || rp.ErrCode == 42001 {
- token, expired, err := QueryAccessToken(int(WxPlat), wxAccessTokenExpires)
- if err != nil {
- return rp, err
- }
- wxAccessToken = token
- wxAccessTokenExpires = expired
- continue
- }
- if rp.ErrCode < 0 {
- time.Sleep(time.Millisecond * 10)
- continue
- }
- return rp, err
- }
- return rp, err
- }
- type ResponseCancelPay struct {
- ErrCode int `json:"errcode"`
- ErrMsg string `json:"errmsg"`
- BillNo string `json:"bill_no"`
- }
- // 取消支付
- func CancelPay(openid string, billNo string) (*ResponseCancelPay, error) {
- req := NewHttpRequest()
- requestData := make(map[string]interface{})
- requestData["openid"] = openid //"oNEBv5CU3aOz7FcWp5ZDlhCNc3-U"
- requestData["appid"] = os.Getenv("WXPAY_APPID") //"wx831355257c862ac2"
- requestData["offer_id"] = os.Getenv("WXPAY_OFFERID") //"1450030892"
- requestData["ts"] = time.Now().Unix()
- requestData["zone_id"] = "1"
- requestData["pf"] = "android"
- requestData["bill_no"] = billNo
- //requestData["pay_item"] = "钻石"
- requestData["sig"] = MakeGetBalanceSig(requestData, cancelPayUri)
- requestData["access_token "] = wxAccessToken
- url := "https://api.weixin.qq.com" + cancelPayUri + "?access_token=" + wxAccessToken
- //url := "https://api.weixin.qq.com/cgi-bin/midas/sandbox/cancelpay?access_token=" + accessToken
- 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(ResponseCancelPay)
- resp.UnmarshalBody(res)
- //log.Warnf("%#v", res)
- return res, nil
- }
- return nil, nil
- }
- type ResponsePresent struct {
- ErrCode int `json:"errcode"`
- ErrMsg string `json:"errmsg"`
- Balance int `json:"balance"`
- BillNo string `json:"bill_no"`
- }
- // 赠送
- func Present(openid string, billNo string, presendCount int) (*ResponsePresent, error) {
- req := NewHttpRequest()
- requestData := make(map[string]interface{})
- requestData["openid"] = openid //"oNEBv5CU3aOz7FcWp5ZDlhCNc3-U"
- requestData["appid"] = os.Getenv("WXPAY_APPID") //"wx831355257c862ac2"
- requestData["offer_id"] = os.Getenv("WXPAY_OFFERID") //"1450030892"
- requestData["ts"] = time.Now().Unix()
- requestData["zone_id"] = "1"
- requestData["pf"] = "android"
- requestData["bill_no"] = billNo
- requestData["present_counts"] = presendCount
- requestData["sig"] = MakeGetBalanceSig(requestData, presentUri)
- requestData["access_token "] = wxAccessToken
- url := "https://api.weixin.qq.com" + presentUri + "?access_token=" + wxAccessToken
- //url := "https://api.weixin.qq.com/cgi-bin/midas/sandbox/present?access_token=" + accessToken
- 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(ResponsePresent)
- resp.UnmarshalBody(res)
- //log.Warnf("%#v", res)
- return res, nil
- }
- return nil, nil
- }
|