197 lines
4.7 KiB
Go
197 lines
4.7 KiB
Go
package pay
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/md5"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/url"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/pkg/errors"
|
|
"go-common/library/log"
|
|
)
|
|
|
|
// Pay is.
|
|
type Pay struct {
|
|
ID string
|
|
Token string
|
|
RechargeShellNotifyURL string
|
|
}
|
|
|
|
// TraceID .
|
|
func (p *Pay) TraceID() string {
|
|
return strconv.FormatInt(time.Now().UnixNano(), 10)
|
|
}
|
|
|
|
// RechargeShellReq .
|
|
type RechargeShellReq struct {
|
|
CustomerID string `json:"customerId"`
|
|
ProductName string `json:"productName"`
|
|
Rate string `json:"rate"`
|
|
NotifyURL string `json:"notifyUrl"`
|
|
Timestamp int64 `json:"timestamp"`
|
|
SignType string `json:"signType"`
|
|
Sign string `json:"sign"`
|
|
Data []RechargeShellData `json:"data"`
|
|
}
|
|
|
|
// RechargeShellData .
|
|
type RechargeShellData struct {
|
|
ThirdOrderNo string `json:"thirdOrderNo"`
|
|
MID int64 `json:"mid"`
|
|
ThirdCoin string `json:"thirdCoin"`
|
|
Brokerage string `json:"brokerage"`
|
|
ThirdCtime int64 `json:"thirdCtime"`
|
|
}
|
|
|
|
// RechargeShell 转入贝壳
|
|
func (p *Pay) RechargeShell(orderID string, mid int64, assetBP int64, shell int64) (params url.Values, jsonData string, err error) {
|
|
var (
|
|
productName = "UGC付费"
|
|
rate = "1.00"
|
|
timestamp = time.Now().Unix() * 1000
|
|
thirdCoin = float64(assetBP) / 100
|
|
brokerage = float64(shell) / 100
|
|
)
|
|
|
|
params = make(url.Values)
|
|
params.Set("customerId", p.ID)
|
|
params.Set("productName", productName)
|
|
params.Set("rate", rate)
|
|
params.Set("notifyUrl", p.RechargeShellNotifyURL)
|
|
params.Set("timestamp", strconv.FormatInt(timestamp, 10))
|
|
params.Set("data", fmt.Sprintf("[{brokerage=%.2f&mid=%d&thirdCoin=%.2f&thirdCtime=%d&thirdOrderNo=%s}]", brokerage, mid, thirdCoin, timestamp, orderID))
|
|
p.Sign(params)
|
|
|
|
data := RechargeShellData{
|
|
ThirdOrderNo: orderID,
|
|
MID: mid,
|
|
ThirdCoin: fmt.Sprintf("%.2f", thirdCoin),
|
|
Brokerage: fmt.Sprintf("%.2f", brokerage),
|
|
ThirdCtime: timestamp,
|
|
}
|
|
req := RechargeShellReq{
|
|
CustomerID: p.ID,
|
|
ProductName: productName,
|
|
Rate: rate,
|
|
NotifyURL: p.RechargeShellNotifyURL,
|
|
Timestamp: timestamp,
|
|
SignType: params.Get("signType"),
|
|
Sign: params.Get("sign"),
|
|
Data: []RechargeShellData{data},
|
|
}
|
|
|
|
payBytes, err := json.Marshal(req)
|
|
if err != nil {
|
|
err = errors.Wrapf(err, "pay.RechargeShell.ToJSON : %s", params.Encode())
|
|
return
|
|
}
|
|
jsonData = string(payBytes)
|
|
return
|
|
}
|
|
|
|
// CheckOrder 对账param
|
|
func (p Pay) CheckOrder(txID string) (params url.Values) {
|
|
params = make(url.Values)
|
|
params.Set("customerId", p.ID)
|
|
params.Set("txIds", txID)
|
|
return
|
|
}
|
|
|
|
// CheckRefundOrder 退款对账param
|
|
func (p Pay) CheckRefundOrder(txID string) (params url.Values) {
|
|
params = make(url.Values)
|
|
params.Set("customerId", p.ID)
|
|
params.Set("txIds", txID)
|
|
return
|
|
}
|
|
|
|
// Query 返回订单查询param
|
|
func (p *Pay) Query(orderID string) (params url.Values) {
|
|
params = make(url.Values)
|
|
params.Set("customerId", p.ID)
|
|
params.Set("orderIds", orderID)
|
|
params.Set("timestamp", strconv.FormatInt(time.Now().Unix()*1000, 10))
|
|
params.Set("traceId", p.TraceID())
|
|
params.Set("version", "1.0")
|
|
return
|
|
}
|
|
|
|
// ToJSON param to json
|
|
func (p *Pay) ToJSON(params url.Values) (j string, err error) {
|
|
var (
|
|
payBytes []byte
|
|
pmap = make(map[string]string)
|
|
)
|
|
for k, v := range params {
|
|
if len(v) > 0 {
|
|
pmap[k] = v[0]
|
|
}
|
|
}
|
|
if payBytes, err = json.Marshal(pmap); err != nil {
|
|
err = errors.Wrapf(err, "pay.ToJSON : %s", params.Encode())
|
|
return
|
|
}
|
|
j = string(payBytes)
|
|
return
|
|
}
|
|
|
|
// DeviceType 支付平台DeviceType
|
|
func (p *Pay) DeviceType(platform string) (t int64) {
|
|
// 支付设备渠道类型, 1 pc 2 webapp 3 app 4jsapi 5 server 6小程序支付 7聚合二维码支付
|
|
switch platform {
|
|
case "ios", "android":
|
|
return 3
|
|
default:
|
|
return 1
|
|
}
|
|
}
|
|
|
|
// Sign 支付平台接口签名
|
|
func (p *Pay) Sign(params url.Values) (err error) {
|
|
params.Set("signType", "MD5")
|
|
sortedStr := params.Encode()
|
|
if sortedStr, err = url.QueryUnescape(sortedStr); err != nil {
|
|
return
|
|
}
|
|
b := bytes.Buffer{}
|
|
b.WriteString(sortedStr)
|
|
b.WriteString("&token=" + p.Token)
|
|
signMD5 := md5.Sum(b.Bytes())
|
|
sign := hex.EncodeToString(signMD5[:])
|
|
params.Set("sign", sign)
|
|
return
|
|
}
|
|
|
|
// Verify 支付平台返回param校验
|
|
func (p *Pay) Verify(params url.Values) (ok bool) {
|
|
var (
|
|
rs = params.Get("sign")
|
|
s string
|
|
)
|
|
ok = false
|
|
defer func() {
|
|
if !ok {
|
|
params.Set("sign", rs)
|
|
log.Error("Verify pay sign error, expect : %s, actual : %s, params : %s", s, rs, params.Encode())
|
|
}
|
|
}()
|
|
if rs == "" {
|
|
return
|
|
}
|
|
params.Del("sign")
|
|
if err := p.Sign(params); err != nil {
|
|
log.Error("Verify pay sign error : %+v", err)
|
|
return
|
|
}
|
|
s = params.Get("sign")
|
|
if rs == s {
|
|
ok = true
|
|
return
|
|
}
|
|
return
|
|
}
|