package eanipay import ( "encoding/json" "errors" "fmt" "net/http" "server/common" "server/modules/pay/base" "server/modules/pay/values" "server/pb" "server/util" "time" "github.com/gogo/protobuf/proto" "github.com/liangdas/mqant/log" ) func NewSub(b *base.Base) { sub := &Sub{ Base: b, } b.HttpType = base.HttpTypeJson b.ShouldSignUpper = true if b.Opt == base.OPTPay { b.Resp = new(PayResp) b.ReqURL = baseURL + payURL } else if b.Opt == base.OPTWithdraw { b.Resp = new(WithdrawResp) b.ReqURL = baseURL + withdrawURL } else if b.Opt == base.OPTPayCB { b.CallbackReq = new(PayCallbackReq) b.CallbackResp.Msg = "success" } else if b.Opt == base.OPTWithdrawCB { b.CallbackReq = new(WithdrawCallbackReq) b.CallbackResp.Msg = "success" } else if b.Opt == base.OPTQueryWithdraw { // 查询 b.Resp = new(QueryWithdrawResp) b.ReqURL = baseURL + queryWithdrawURL } else if b.Opt == base.OPTQueryPay { // 查询 b.Resp = new(QueryPayResp) b.ReqURL = baseURL + queryPayURL } else { return } b.Sub = sub } type Sub struct { Base *base.Base } func (s *Sub) PackHeader(header http.Header) { header.Set("Accept", "application/json") url := baseURL if s.Base.Opt == base.OPTPay { url += payURL } else if s.Base.Opt == base.OPTWithdraw { url += withdrawURL } else if s.Base.Opt == base.OPTQueryWithdraw { url += queryWithdrawURL } else if s.Base.Opt == base.OPTQueryPay { url += queryPayURL } randomStr := util.GetSimpleRandomString(10) bodyStr, _ := json.Marshal(s.Base.ReqData) now := time.Now().UnixMilli() sign := Sign(string(bodyStr), fmt.Sprintf("%d", now), randomStr, url) header.Set("Authorization", fmt.Sprintf(`V2_SHA256 appId=%s,sign=%s,timestamp=%d,nonce=%s`, appID, sign, now, randomStr)) } func (s *Sub) PackReq() interface{} { if s.Base.Opt == base.OPTPay { return s.PackPayReq() } else if s.Base.Opt == base.OPTWithdraw { return s.PackWithdrawReq() } return nil } func (s *Sub) GetResp() (proto.Message, error) { log.Debug("resp:%v", s.Base.Resp) if s.Base.Opt == base.OPTPay { resp := s.Base.Resp.(*PayResp) if resp.Data.Action.URL == "" { return nil, errors.New("pay fail") } return &pb.InnerRechargeResp{APIOrderID: resp.Data.PaymentNo, URL: resp.Data.Action.URL, Channel: uint32(values.EaniPay)}, nil } else if s.Base.Opt == base.OPTWithdraw { resp := s.Base.Resp.(*WithdrawResp) if s.Base.Status == 0 && resp.Code != "OK" { return nil, errors.New("withdraw fail") } return &pb.InnerWithdrawResp{APIOrderID: resp.Data.PayoutNo, Channel: uint32(values.EaniPay)}, nil } return nil, errors.New("unknown opt") } func (s *Sub) PackPayReq() interface{} { r := s.Base.PayReq send := &PayReq{ MerchantTradeNo: r.OrderID, Amount: fmt.Sprintf("%d", r.Amount), Currency: "INR", Description: "BW", Payer: Payer{UserID: fmt.Sprintf("%d", r.UID), Name: r.Name, Email: r.Email, Phone: r.Phone}, PayMethod: struct { Type string `json:"type"` // UPI }{Type: "UPI"}, TradeEnv: struct { IP string `json:"ip"` }{IP: r.IP}, NotifyUrl: values.GetPayCallback(values.EaniPay), ReturnUrl: values.GetPayCallback(values.EaniPay), } s.Base.ReqData = send return send } func (s *Sub) PackWithdrawReq() interface{} { r := s.Base.WithdrawReq send := &WithdrawReq{ MerchantTradeNo: r.OrderID, Amount: fmt.Sprintf("%d", r.Amount), Currency: "INR", Description: "BW", NotifyUrl: values.GetWithdrawCallback(values.EaniPay), } if r.PayType == common.WithdrawTypeBank { send.PayoutMethod.Type = "BANK_ACCOUNT" send.PayoutMethod.Mode = "IMPS" send.PayoutMethod.BankCode = r.PayCode send.PayoutMethod.BankName = r.BankName send.PayoutMethod.AccountNumber = r.CardNo send.PayoutMethod.PayeeName = r.Name send.PayoutMethod.PayeePhone = r.Phone send.PayoutMethod.PayeeEmail = r.Email send.PayoutMethod.PayeeAddress = r.Address } else { return nil } s.Base.ReqData = send return send } func (s *Sub) CheckSign(str string) bool { log.Debug("callback:%v", s.Base.CallbackReq) signStr := s.Base.C.GetHeader("Authorization") signData := parseData(signStr) if s.Base.Opt == base.OPTPayCB { req := s.Base.CallbackReq.(*PayCallbackReq) s.Base.CallbackResp.OrderID = req.Data.MerchantTradeNo if req.Data.Status == "PENDING" || req.Data.Status == "PROCESSING" { return false } s.Base.CallbackResp.APIOrderID = req.Data.PaymentNo s.Base.CallbackResp.Success = req.Data.Status == "PAID" return Sign(str, signData.Timestamp, signData.Nonce, values.GetPayCallback(values.EaniPay)) == signData.Sign } else if s.Base.Opt == base.OPTWithdrawCB { req := s.Base.CallbackReq.(*WithdrawCallbackReq) s.Base.CallbackResp.OrderID = req.Data.MerchantTradeNo if req.Data.Status == "PENDING" || req.Data.Status == "PROCESSING" { return false } s.Base.CallbackResp.Success = req.Data.Status == "PAID" return Sign(str, signData.Timestamp, signData.Nonce, values.GetWithdrawCallback(values.EaniPay)) == signData.Sign } return false } func Sign(bodyStr, t, ran, url string) string { signStr := fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n", appID, appSecret, "POST", url, t, ran, bodyStr, ) sign := util.CalculateSHA256(signStr) log.Debug("signStr:%s,sign:%s", signStr, sign) return sign }