mirror of
https://github.com/iLoveElysia/openbilibili.git
synced 2026-06-08 05:58:29 -05:00
183 lines
4.9 KiB
Go
183 lines
4.9 KiB
Go
package pay
|
||
|
||
import (
|
||
"bytes"
|
||
"crypto/md5"
|
||
"encoding/hex"
|
||
"encoding/json"
|
||
"net/url"
|
||
"strconv"
|
||
"time"
|
||
|
||
"go-common/library/log"
|
||
|
||
"github.com/pkg/errors"
|
||
)
|
||
|
||
// Pay is.
|
||
type Pay struct {
|
||
ID string
|
||
Token string
|
||
OrderTTL int
|
||
NotifyURL string
|
||
RefundNotifyURL string
|
||
}
|
||
|
||
// Create 返回订单创建param
|
||
func (p *Pay) Create(orderID string, productID int64, price int64, deviceType int64, serviceType int, mid int64, title string) (params url.Values) {
|
||
params = make(url.Values)
|
||
params.Set("customerId", p.ID)
|
||
params.Set("serviceType", strconv.Itoa(serviceType))
|
||
params.Set("orderId", orderID)
|
||
params.Set("orderCreateTime", strconv.FormatInt(time.Now().Unix()*1000, 10))
|
||
params.Set("orderExpire", strconv.Itoa(p.OrderTTL))
|
||
params.Set("payAmount", strconv.FormatInt(price, 10))
|
||
params.Set("originalAmount", strconv.FormatInt(price, 10))
|
||
params.Set("deviceType", strconv.FormatInt(deviceType, 10))
|
||
params.Set("notifyUrl", p.NotifyURL)
|
||
params.Set("productId", strconv.FormatInt(productID, 10))
|
||
params.Set("showTitle", title)
|
||
params.Set("traceId", p.TraceID())
|
||
params.Set("timestamp", strconv.FormatInt(time.Now().Unix()*1000, 10))
|
||
params.Set("version", "1.0")
|
||
params.Set("uid", strconv.FormatInt(mid, 10))
|
||
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
|
||
}
|
||
|
||
// TraceID 生成traceID
|
||
func (p *Pay) TraceID() string {
|
||
return strconv.FormatInt(time.Now().UnixNano(), 10)
|
||
}
|
||
|
||
// Refund 原路返回退款params
|
||
func (p *Pay) Refund(txID string, refundFee int64, refundDesc string) (params url.Values) {
|
||
params = make(url.Values)
|
||
params.Set("customerId", p.ID)
|
||
params.Set("txId", txID)
|
||
params.Set("totalAmount", strconv.FormatInt(refundFee, 10))
|
||
params.Set("refundAmount", strconv.FormatInt(refundFee, 10))
|
||
params.Set("refundDesc", refundDesc)
|
||
params.Set("notifyUrl", p.RefundNotifyURL)
|
||
params.Set("version", "1.0")
|
||
params.Set("traceId", p.TraceID())
|
||
params.Set("timestamp", strconv.FormatInt(time.Now().Unix()*1000, 10))
|
||
return
|
||
}
|
||
|
||
// Cancel 返回订单取消param
|
||
func (p *Pay) Cancel(orderID string) (params url.Values) {
|
||
params = make(url.Values)
|
||
params.Set("customerId", p.ID)
|
||
params.Set("orderId", orderID)
|
||
params.Set("timestamp", strconv.FormatInt(time.Now().Unix()*1000, 10))
|
||
params.Set("traceId", p.TraceID())
|
||
params.Set("version", "1.0")
|
||
return
|
||
}
|
||
|
||
// ToJSON 将param转换为支付平台请求的body: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 通过platform获得支付平台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
|
||
}
|
||
}
|
||
|
||
// ServiceType 通过platform获得支付平台ServiceType
|
||
func (p *Pay) ServiceType(platform string) (t int) {
|
||
/*
|
||
业务方业务类型,用于业务方定制支付渠道,不同的serviceType可以配置成不同的支付渠道列表
|
||
每个渠道列表可以自定义顺序,以下值具有特殊含义:
|
||
|
||
1. 7 签约代扣类,如微信代扣,支付宝代扣 (5.25 支持)
|
||
2. 100 表示IAP支付 (5.24 支持)
|
||
3. 100 IAP代扣也传100,根据subscribeType区分是不是代扣
|
||
4. 99 表示 客户端B币快捷支付 (5.26 支持)
|
||
5 98 表示 业务方B币快捷支付(1.1 B币支付)
|
||
*/
|
||
switch platform {
|
||
case "ios", "android":
|
||
return 0
|
||
default:
|
||
return 99
|
||
}
|
||
}
|
||
|
||
// Sign 对param进行签名
|
||
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
|
||
}
|