印度包网
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.

359 lines
9.4 KiB

3 months ago
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, &paramsMap)
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, &paramsMap)
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, &paramsMap)
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
}