You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
358 lines
9.4 KiB
358 lines
9.4 KiB
package robuspay |
|
|
|
import ( |
|
"encoding/json" |
|
"errors" |
|
"fmt" |
|
"net/http" |
|
"server/modules/pay/base" |
|
"server/modules/pay/values" |
|
"server/pb" |
|
"server/util" |
|
"sort" |
|
"strings" |
|
"time" |
|
|
|
"github.com/gogo/protobuf/proto" |
|
jsoniter "github.com/json-iterator/go" |
|
"github.com/liangdas/mqant/log" |
|
) |
|
|
|
func NewSub(b *base.Base) { |
|
sub := &Sub{ |
|
Base: b, |
|
} |
|
b.HttpType = base.HttpTypeJson |
|
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 = "OK" |
|
b.HttpType = base.HttpTypeForm |
|
} else if b.Opt == base.OPTWithdrawCB { |
|
b.CallbackReq = new(WithdrawCallbackReq) |
|
b.CallbackResp.Msg = "OK" |
|
b.HttpType = base.HttpTypeForm |
|
} 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) { |
|
} |
|
|
|
func (s *Sub) PackReq() interface{} { |
|
if s.Base.Opt == base.OPTPay { |
|
return s.PackPayReq() |
|
} else if s.Base.Opt == base.OPTWithdraw { |
|
return s.PackWithdrawReq() |
|
} else if s.Base.Opt == base.OPTQueryWithdraw { |
|
return s.PackQueryWithdrawReq() |
|
} else if s.Base.Opt == base.OPTQueryPay { |
|
return s.PackQueryPayReq() |
|
} |
|
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 s.Base.Status == 0 && resp.RetCode != "0000" { // 错误 |
|
log.Error("robus pay err, %+v", resp) |
|
return nil, errors.New("pay fail") |
|
} |
|
var payurl string |
|
if resp.Data.Type == "" || resp.Data.Type == "payurl" { |
|
payurl = resp.Data.PayUrl |
|
} else { |
|
payurl = resp.Data.PayData |
|
} |
|
if resp.Data.PayUrl == "" { |
|
log.Error("robus pay link is nil, %+v", resp) |
|
return nil, errors.New("pay fail") |
|
} |
|
return &pb.InnerRechargeResp{APIOrderID: resp.Data.OrderNo, URL: payurl, Channel: uint32(values.RobusPay)}, nil |
|
} else if s.Base.Opt == base.OPTWithdraw { |
|
resp := s.Base.Resp.(*WithdrawResp) |
|
// notice: 提现的时候,未知错误不能当做错误返回 |
|
if s.Base.Status == 0 && resp.RetCode != "0000" { |
|
log.Error("robus withdraw err, %+v", resp) |
|
return nil, errors.New("withdraw fail") |
|
} |
|
return &pb.InnerWithdrawResp{APIOrderID: resp.Data.OrderNo, Channel: uint32(values.RobusPay)}, nil |
|
} else if s.Base.Opt == base.OPTQueryWithdraw { |
|
resp := s.Base.Resp.(*QueryWithdrawResp) |
|
ret := &pb.InnerQueryWithdrawResp{} |
|
if resp.RetCode != "0000" { // 错误 |
|
log.Error("robus query withdraw err, %+v", resp) |
|
s.Base.QueryWithdrawResp.Status = base.QueryStatusUnknown |
|
return ret, nil |
|
} |
|
s.Base.QueryWithdrawResp.OrderID = resp.Data.MerchantOrderNo |
|
if s.Base.Status != 0 { |
|
s.Base.QueryWithdrawResp.Status = base.QueryStatusUnknown |
|
} else { |
|
if resp.Data.Success == 1 { |
|
s.Base.QueryWithdrawResp.Status = base.QueryStatusOrderSuccess |
|
} else if resp.Data.Success == -1 { |
|
s.Base.QueryWithdrawResp.Status = base.QueryStatusFail |
|
} else { |
|
s.Base.QueryWithdrawResp.Status = base.QueryStatusUnknown |
|
} |
|
} |
|
return ret, nil |
|
} else if s.Base.Opt == base.OPTQueryPay { |
|
resp := s.Base.Resp.(*QueryPayResp) |
|
ret := &pb.InnerQueryWithdrawResp{} |
|
if resp.RetCode != "0000" { // 错误 |
|
log.Error("robus query pay err, %+v", resp) |
|
s.Base.QueryPayResp.Status = base.QueryStatusUnknown |
|
return ret, nil |
|
} |
|
|
|
s.Base.QueryWithdrawResp.OrderID = resp.Data.MerchantOrderNo |
|
if s.Base.Status != 0 { |
|
s.Base.QueryPayResp.Status = base.QueryStatusUnknown |
|
} else { |
|
if resp.Data.Success == 1 { |
|
s.Base.QueryPayResp.Status = base.QueryStatusOrderSuccess |
|
} else if resp.Data.Success == -1 { |
|
s.Base.QueryPayResp.Status = base.QueryStatusFail |
|
} else { |
|
s.Base.QueryPayResp.Status = base.QueryStatusUnknown |
|
} |
|
} |
|
return ret, nil |
|
} |
|
return nil, errors.New("unknown opt") |
|
} |
|
|
|
func (s *Sub) PackPayReq() interface{} { |
|
r := s.Base.PayReq |
|
send := &PayReq{ |
|
MerchantNo: merchantId, |
|
MerchantOrderNo: r.OrderID, |
|
Amount: fmt.Sprintf("%d.00", r.Amount), |
|
Name: r.Name, |
|
Email: r.Email, |
|
Mobile: r.Phone, |
|
RequestTime: time.Now().Format(time.DateTime), |
|
Method: "121001", |
|
AsyncCallbackUrl: s.Base.GetPayCallbackURL(), |
|
SyncCallbackUrl: s.Base.GetPayCallbackURL(), |
|
SignType: "MD5", |
|
Country: "IN", |
|
} |
|
signValue, err := s.GetSign(send) |
|
if err != nil { |
|
log.Error("get sign err, %s", err.Error()) |
|
} |
|
send.Sign = signValue |
|
return send |
|
} |
|
|
|
func (s *Sub) PackWithdrawReq() interface{} { |
|
r := s.Base.WithdrawReq |
|
paramBytes, _ := json.Marshal(map[string]string{ |
|
"accountName": r.Name, |
|
"accountNo": r.CardNo, |
|
"bankCode": r.PayCode, |
|
}) |
|
send := &WithdrawReq{ |
|
MerchantNo: merchantId, |
|
MerchantOrderNo: r.OrderID, |
|
Amount: fmt.Sprintf("%d.00", r.Amount), |
|
Name: r.Name, |
|
Email: r.Email, |
|
Mobile: r.Phone, |
|
RequestTime: time.Now().Format(time.DateTime), |
|
AsyncCallbackUrl: s.Base.GetWithdrawCallbackURL(), |
|
Method: "121002", |
|
WithdrawCode: "1002", |
|
WithdrawParam: string(paramBytes), |
|
SignType: "MD5", |
|
Country: "IN", |
|
} |
|
signValue, err := s.GetSign(send) |
|
if err != nil { |
|
log.Error("get sign err, %s", err.Error()) |
|
} |
|
send.Sign = signValue |
|
return send |
|
} |
|
|
|
func (s *Sub) GetSignStr(body interface{}) (sign, signStr string) { |
|
bodyBytes, err := jsoniter.Marshal(body) |
|
if err != nil { |
|
log.Error("marshal err, %s", err.Error()) |
|
return |
|
} |
|
var ( |
|
paramsMap map[string]interface{} |
|
params []string |
|
paramsValue []string |
|
) |
|
err = jsoniter.Unmarshal(bodyBytes, ¶msMap) |
|
if err != nil { |
|
log.Error("unmarshal err, %s", err.Error()) |
|
return |
|
} |
|
|
|
for k, v := range paramsMap { |
|
if k == "sign" { |
|
sign = v.(string) |
|
continue |
|
} |
|
params = append(params, k) |
|
} |
|
sort.Strings(params) |
|
for _, v := range params { |
|
value := fmt.Sprintf("%+v", paramsMap[v]) |
|
switch (paramsMap[v]).(type) { |
|
case float32: |
|
value = fmt.Sprintf("%d", int(paramsMap[v].(float32))) |
|
case float64: |
|
value = fmt.Sprintf("%d", int(paramsMap[v].(float64))) |
|
} |
|
paramsValue = append(paramsValue, fmt.Sprintf("%s=%+v", v, value)) |
|
} |
|
signStr = strings.Join(paramsValue, "&") |
|
return |
|
} |
|
|
|
func (s *Sub) GetSign(body interface{}) (sign string, err error) { |
|
bodyBytes, err := jsoniter.Marshal(body) |
|
if err != nil { |
|
log.Error("marshal err, %s", err.Error()) |
|
return |
|
} |
|
var paramsMap map[string]interface{} |
|
err = jsoniter.Unmarshal(bodyBytes, ¶msMap) |
|
if err != nil { |
|
log.Error("unmarshal err, %s", err.Error()) |
|
return |
|
} |
|
|
|
params := make([]string, 0) |
|
for k, v := range paramsMap { |
|
if k == "sign" || v == nil || v == "" { |
|
continue |
|
} |
|
params = append(params, k) |
|
} |
|
sort.Strings(params) |
|
|
|
paramsValue := make([]string, 0) |
|
for _, k := range params { |
|
paramsValue = append(paramsValue, fmt.Sprintf("%s=%v", k, paramsMap[k])) |
|
} |
|
|
|
paramsValue = append(paramsValue, "key="+key) |
|
signStr := strings.Join(paramsValue, "&") |
|
sign = strings.ToUpper(util.CalculateMD5(signStr)) |
|
return |
|
} |
|
|
|
func (s *Sub) checkSign(body string) (pass bool, err error) { |
|
var sign string |
|
mySign, err := s.GetSign(s.Base.CallbackReq) |
|
if err != nil { |
|
log.Error("robus get sign err, %s", err.Error()) |
|
return false, err |
|
} |
|
var ( |
|
paramsMap map[string]interface{} |
|
) |
|
err = jsoniter.UnmarshalFromString(body, ¶msMap) |
|
if err != nil { |
|
log.Error("unmarshal err, %s", err.Error()) |
|
return |
|
} |
|
if paramsMap["sign"] == nil { |
|
return false, errors.New("sign is nil") |
|
} else { |
|
sign = paramsMap["sign"].(string) |
|
} |
|
return sign == mySign, nil |
|
} |
|
|
|
func (s *Sub) CheckSign(str string) bool { |
|
log.Debug("callback:%v", s.Base.CallbackReq) |
|
data, _ := json.Marshal(s.Base.CallbackReq) |
|
pass, err := s.checkSign(string(data)) |
|
if err != nil { |
|
log.Error("check sign err, %s", err.Error()) |
|
return false |
|
} |
|
|
|
if s.Base.Opt == base.OPTPayCB { |
|
req := s.Base.CallbackReq.(*PayCallbackReq) |
|
s.Base.CallbackResp.OrderID = req.MerchantOrderNo |
|
s.Base.CallbackResp.APIOrderID = req.OrderNo |
|
s.Base.CallbackResp.Success = req.Success == "1" |
|
if req.Success != "1" { |
|
s.Base.CallbackResp.FailMessage = fmt.Sprintf("返回结果不为1") |
|
} |
|
return pass |
|
} else if s.Base.Opt == base.OPTWithdrawCB { |
|
req := s.Base.CallbackReq.(*WithdrawCallbackReq) |
|
s.Base.CallbackResp.OrderID = req.MerchantOrderNo |
|
s.Base.CallbackResp.APIOrderID = req.OrderNo |
|
s.Base.CallbackResp.Success = req.Success == "1" |
|
if req.Success != "1" { |
|
s.Base.CallbackResp.FailMessage = fmt.Sprintf("返回结果不为1") |
|
} |
|
return pass |
|
} |
|
return false |
|
} |
|
|
|
func (s *Sub) PackQueryWithdrawReq() interface{} { |
|
r := s.Base.QueryWithdrawReq |
|
send := &QueryWithdrawReq{ |
|
MerchantNo: merchantId, |
|
MerchantOrderNo: r.OrderID, |
|
SignType: "MD5", |
|
Sign: "", |
|
} |
|
signValue, err := s.GetSign(send) |
|
if err != nil { |
|
log.Error("get sign err, %s", err.Error()) |
|
} |
|
send.Sign = signValue |
|
|
|
return send |
|
} |
|
|
|
func (s *Sub) PackQueryPayReq() interface{} { |
|
r := s.Base.QueryPayReq |
|
send := &QueryPayReq{ |
|
MerchantNo: merchantId, |
|
MerchantOrderNo: r.OrderID, |
|
SignType: "MD5", |
|
Sign: "", |
|
} |
|
signValue, err := s.GetSign(send) |
|
if err != nil { |
|
log.Error("get sign err, %s", err.Error()) |
|
} |
|
send.Sign = signValue |
|
|
|
return send |
|
}
|
|
|