This commit is contained in:
邹宗楠
2023-04-06 18:25:24 +08:00
parent 18572ce050
commit 88e7b96fec
10 changed files with 457 additions and 18 deletions

View File

@@ -17,9 +17,14 @@ const (
// KuaiShouBashUrl 基础域名
KuaiShouBashUrl = "https://open.kuaishou.com" // 域名
KuaiShouAuthLogin = KuaiShouBashUrl + "/oauth2/mp/code2session" // 授权登录
KuaiShouGetToken = KuaiShouBashUrl + "/oauth2/access_token" // 获取授权token
KuaiShouPreCreateOrder = KuaiShouBashUrl + "/openapi/mp/developer/epay/create_order" // 预下单接口
KuaiShouAuthLogin = KuaiShouBashUrl + "/oauth2/mp/code2session" // 授权登录
KuaiShouGetToken = KuaiShouBashUrl + "/oauth2/access_token" // 获取授权token
KuaiShouPreCreateOrder = KuaiShouBashUrl + "/openapi/mp/developer/epay/create_order" // 预下单接口
KuaiShouGetOrderDetail = KuaiShouBashUrl + "/openapi/mp/developer/epay/query_order" // 获取订单详情接口
KuaiShouRefundOrder = KuaiShouBashUrl + "/openapi/mp/developer/epay/apply_refund" // 订单退款
KuaiShouRefundOrderDetail = KuaiShouBashUrl + "/openapi/mp/developer/epay/query_refund" // 订单退款详情
KuaiShouGetSettleOrder = KuaiShouBashUrl + "/openapi/mp/developer/epay/settle" // 刷新订单结算信息
KuaiShouQuerySettleOrder = KuaiShouBashUrl + "/openapi/mp/developer/epay/query_settle" // 查询订单的结算信息
)
type API struct {
@@ -82,8 +87,9 @@ func (a *API) GetToken() error {
func (a *API) AccessAPI1(url string, params map[string]interface{}) (retVal map[string]interface{}, err error) {
err = platformapi.AccessPlatformAPIWithRetry(a.client,
func() *http.Request {
globals.SugarLogger.Debugf("====param := %s", utils.Format4Output(params, false))
request, _ := http.NewRequest(http.MethodPost, url, strings.NewReader(utils.Map2URLValues(params).Encode()))
request.Header.Set("Content-Type", "application/json")
request.Header.Set("Content-Type", "application/json;charset=UTF-8")
return request
},
a.config,
@@ -137,8 +143,6 @@ func (a *API) sign(param map[string]interface{}) string {
sort.Strings(paramsArr)
globals.SugarLogger.Debugf("param := %s", utils.Format4Output(param, false))
globals.SugarLogger.Debugf("paramsArr := %s", utils.Format4Output(paramsArr, false))
signParma := make([]string, len(paramsArr))
for k, v := range paramsArr {
if !utils.IsNil(param[v]) {

View File

@@ -0,0 +1,93 @@
package kuaishou_mini
import (
"encoding/json"
"errors"
"git.rosy.net.cn/baseapi/utils"
"io/ioutil"
"net/http"
)
const (
CallbackTypePay = "PAYMENT" // 支付回调
CallbackTypeRefund = "REFUND" // 退款回调
CallbackTypeSettle = "SETTLE" // 结算回调
OrderPayStatusHandleing = "PROCESSING" // 支付订单处理中
OrderPayStatusSuccess = "SUCCESS" // 订单支付成功
OrderPayStatusFailed = "FAILED" // 订单支付失败
)
// KauiShouCallback 回调处理
func (a *API) KauiShouCallback(request *http.Request) (*CallBackDetail, *RefundCallBack, string, string, error) {
data, err := ioutil.ReadAll(request.Body)
if err != nil {
return nil, nil, "", "-1", err
}
var callback *KauiShouCallbackRes
if err := json.Unmarshal(data, &callback); err != nil {
return nil, nil, "", "-1", err
}
switch callback.BizType {
case CallbackTypePay:
var payCallback *CallBackDetail
if value, ok := callback.Data.(string); ok {
if err := json.Unmarshal([]byte(value), &payCallback); err != nil {
return nil, nil, "", callback.MessageId, err
}
} else {
if err := json.Unmarshal([]byte(utils.Interface2String(value)), &payCallback); err != nil {
return nil, nil, "", callback.MessageId, err
}
}
return payCallback, nil, CallbackTypePay, callback.MessageId, err
case CallbackTypeRefund:
var refundCallback *RefundCallBack
if value, ok := callback.Data.(string); ok {
if err := json.Unmarshal([]byte(value), &refundCallback); err != nil {
return nil, nil, "", callback.MessageId, err
}
} else {
if err := json.Unmarshal([]byte(utils.Interface2String(value)), &refundCallback); err != nil {
return nil, nil, "", callback.MessageId, err
}
}
return nil, refundCallback, CallbackTypeRefund, callback.MessageId, err
case CallbackTypeSettle:
return nil, nil, "", callback.MessageId, errors.New("无效回调类型")
default:
return nil, nil, "", callback.MessageId, errors.New("无效回调类型")
}
}
// KuaiShouRefundCallBack 快手退款回调
//func (a *API) KuaiShouRefundCallBack(request *http.Request) (*RefundCallBack, error) {
// data, err := ioutil.ReadAll(request.Body)
// if err != nil {
// return nil, err
// }
//
// var callback *RefundCallBack
// if err := json.Unmarshal(data, &callback); err != nil {
// return nil, err
// }
//
// return callback, err
//}
// KuaiShouSettleCallBack 当订单结算成功之后,快手小程序服务端会通过 post 方式回调开发者提供的 HTTP 接口
//func (a *API) KuaiShouSettleCallBack(request *http.Request) (*SettleCallback, error) {
// data, err := ioutil.ReadAll(request.Body)
// if err != nil {
// return nil, err
// }
//
// var callback *SettleCallback
// if err := json.Unmarshal(data, &callback); err != nil {
// return nil, err
// }
//
// return callback, err
//}

View File

@@ -42,8 +42,158 @@ type PreCreateOrderReq struct {
CancelOrder int64 `json:"cancel_order"` // 该字段表示创建订单的同时是否覆盖之前已存在的订单。
}
// PreCreateOrderResponse 预下单返回参数
type PreCreateOrderResponse struct {
Result int `json:"result"`
ErrorMsg string `json:"error_msg"`
OrderInfo string `json:"order_info"` //拉起收银台的 orderInfo
}
// GetOrderDetailRes 获取支付订单详情
type GetOrderDetailRes struct {
Result int `json:"result"`
ErrorMsg string `json:"error_msg"`
PaymentInfo string `json:"payment_info"` //拉起收银台的 orderInfo
}
type PaymentInfo struct {
TotalAmount int64 `json:"total_amount"` // 预下单用户支付金额
PayStatus string `json:"pay_status"` // 支付状态。 取值: PROCESSING-处理中SUCCESS-成功FAILED-失败 TIMEOUT-超时
PayTime int64 `json:"pay_time"` // 订单支付时间,单位为毫秒时间戳。
PayChannel string `json:"pay_channel"` // 支付渠道。取值UNKNOWN - 未知WECHAT-微信 ALIPAY-支付宝。(注如果用户还未支付这里返回的是UNKNOWN.
OutOrderNo string `json:"out_order_no"` // 开发者下单单号
KsOrderNo string `json:"ks_order_no"` // 快手小程序平台订单号
ExtraInfo string `json:"extra_info"` // 订单来源信息,历史订单为""
EnablePromotion bool `json:"enable_promotion"` // 是否参与分销true:分销false:非分销
PromotionAmount int64 `json:"promotion_amount"` // 预计分销金额,单位:分
OpenId string `json:"open_id"` // 订单对应的用户open id
OrderStatus int64 `json:"order_status"` // 开发者回传的订单同步状态
}
// KauiShouCallbackRes 快手支付回调
type KauiShouCallbackRes struct {
Data interface{} `json:"data"`
MessageId string `json:"message_id"` // 当前回调消息的唯一ID在同一个消息多次通知时保持一致。
BizType string `json:"biz_type"` // 业务类型。取值PAYMENT-支付
AppId string `json:"app_id"` // 当前小程序的AppID
Timestamp int64 `json:"timestamp"` // 流程变动的时间戳
}
type CallBackDetail struct {
Channel string `json:"channel"` // 支付渠道。取值UNKNOWN - 未知WECHAT-微信ALIPAY-支付宝
OutOrderNo string `json:"out_order_no"` // 商户系统内部订单号
Attach string `json:"attach"` // 预下单时携带的开发者自定义信息
Status string `json:"status"` // 订单支付状态。 取值: PROCESSING-处理中SUCCESS-成功FAILED-失败
KsOrderNo string `json:"ks_order_no"` // 快手小程序平台订单号
OrderAmount int `json:"order_amount"` // 订单金额
TradeNo string `json:"trade_no"` // 用户侧支付页交易单号
ExtraInfo string `json:"extra_info"` // 订单来源信息,同支付查询接口
EnablePromotion bool `json:"enable_promotion"` // 是否参与分销true:分销false:非分销
PromotionAmount int `json:"promotion_amount"` // 预计分销金额,单位:分
}
// RefundParam 申请退单参数
type RefundParam struct {
OutOrderNo string `json:"out_order_no"` // 开发者需要发起退款的支付订单号
OutRefundNo string `json:"out_refund_no"` // 开发者的退款单号
Reason string `json:"reason"` // 退款理由
Attach string `json:"attach"` // 开发者自定义字段,回调原样回传
NotifyUrl string `json:"notify_url"` // 通知URL必须为直接可访问的URL不允许携带查询串。
RefundAmount int64 `json:"refund_amount"` // 用户退款金额,单位为分。不允许传非整数的数值
Sign string `json:"sign"` // 签名
MultiCopiesGoodsInfo string `json:"multi_copies_goods_info"` // 单商品购买多份场景,示例值:[{"copies":2}] 内容见multi_copies_goods_info字段说明
}
// RefundRes 申请退款返回参数
type RefundRes struct {
Result int `json:"result"`
ErrorMsg string `json:"error_msg"`
RefundNo string `json:"refund_no"`
}
// RefundOrderDetail 获取退款订单详情
type RefundOrderDetail struct {
Result int `json:"result"`
ErrorMsg string `json:"error_msg"`
RefundInfo string `json:"refund_info"`
}
// RefundInfo 获取申请退款详情
type RefundInfo struct {
KsOrderNo string `json:"ks_order_no"`
RefundStatus string `json:"refund_status"`
RefundNo string `json:"refund_no"`
KsRefundType string `json:"ks_refund_type"`
RefundAmount int `json:"refund_amount"`
KsRefundNo string `json:"ks_refund_no"`
}
// RefundCallBack 快手退款回调
type RefundCallBack struct {
//Data struct {
OutRefundNo string `json:"out_refund_no"` // 开发者的退款单号
RefundAmount int `json:"refund_amount"` // 退款金额
Attach string `json:"attach"` // 预下单时携带的开发者自定义信息
Status string `json:"status"` // 退款状态。 取值: PROCESSING-处理中SUCCESS-成功FAILED-失败
KsOrderNo string `json:"ks_order_no"` // 快手小程序平台订单号
KsRefundNo string `json:"ks_refund_no"` // 快手小程序平台退款单号
KsRefundType string `json:"ks_refund_type"` // 退款账户说明[]
//} `json:"data"`
//MessageId string `json:"message_id"`
//BizType string `json:"biz_type"`
//AppId string `json:"app_id"`
//Timestamp int64 `json:"timestamp"`
}
// OrderSettleAccountParam 发起订单结算请求参数
type OrderSettleAccountParam struct {
OutOrderNo string `json:"out_order_no"`
OutSettleNo string `json:"out_settle_no"`
Reason string `json:"reason"`
Attach string `json:"attach"`
NotifyUrl string `json:"notify_url"`
Sign string `json:"sign"`
SettleAmount int64 `json:"settle_amount"`
MultiCopiesGoodsInfo string `json:"multi_copies_goods_info"`
}
// OrderSettleAccountRes 发起订单结算返回参数
type OrderSettleAccountRes struct {
Result int `json:"result"`
ErrorMsg string `json:"error_msg"`
SettleNo string `json:"settle_no"`
}
// QuerySettleInfoRes 查询订单结算信息
type QuerySettleInfoRes struct {
Result int `json:"result"`
ErrorMsg string `json:"error_msg"`
SettleInfo string `json:"settle_info"`
}
type SettleInfo struct {
SettleNo string `json:"settle_no"`
TotalAmount int `json:"total_amount"`
SettleAmount int `json:"settle_amount"`
SettleStatus string `json:"settle_status"`
KsOrderNo string `json:"ks_order_no"`
KsSettleNo string `json:"ks_settle_no"`
}
// SettleCallback 快手结算回调
type SettleCallback struct {
//Data struct {
OutSettleNo string `json:"out_settle_no"` // 外部结算单号,即开发者结算请求的单号。
Attach string `json:"attach"` // 预下单时携带的开发者自定义信息
SettleAmount int `json:"settle_amount"` // 结算后给商户的金额,单位:分
Status string `json:"status"` // 结算状态。 取值: PROCESSING-处理中SUCCESS-成功FAILED-失败
KsOrderNo string `json:"ks_order_no"` // 快手小程序平台订单号。
KsSettleNo string `json:"ks_settle_no"` // 快手小程序平台结算单号。
EnablePromotion bool `json:"enable_promotion"` // 是否参与分销true:分销false:非分销
PromotionAmount int `json:"promotion_amount"` // 预计分销金额,单位:分
//} `json:"data"`
//BizType string `json:"biz_type"`
//MessageId string `json:"message_id"`
//AppId string `json:"app_id"`
//Timestamp int64 `json:"timestamp"`
}

View File

@@ -1,6 +1,7 @@
package kuaishou_mini
import (
"encoding/json"
"errors"
"fmt"
"git.rosy.net.cn/baseapi/utils"
@@ -31,6 +32,127 @@ func (a *API) PreCreateOrder(param *PreCreateOrderReq) (string, error) {
return order.OrderInfo, nil
}
// GetOrderDetail 订单详情查询接口
func (a *API) GetOrderDetail(outOrderNo string) (*PaymentInfo, error) {
data, err := a.AccessAPI1(KuaiShouGetOrderDetail, map[string]interface{}{"out_order_no": outOrderNo})
if err != nil {
return nil, err
}
orderDetail := &GetOrderDetailRes{}
if err := utils.Map2StructByJson(data, orderDetail, false); err != nil {
return nil, err
}
if orderDetail.Result != 1 {
return nil, err
}
if orderDetail.PaymentInfo == "" {
return nil, errors.New("快手支付订单详情返回值为空")
}
paymentInfo := &PaymentInfo{}
if err := json.Unmarshal([]byte(orderDetail.PaymentInfo), paymentInfo); err != nil {
return nil, err
}
return paymentInfo, err
}
// RefundOrder 支付请求退款接口
// 在途资金中的所有货款均是与订单关联的,只有当该订单在途资金中剩余金额超过退款金额时,才可以进行在途资金的退款。
// 当可提现金额也不足退款金额时,会退款失败,为了避免出现订单无法退款的情况出现,请根据业务情况自行保留一部分可提现金额在系统中
func (a *API) RefundOrder(param *RefundParam) (refundNo string, err error) {
data, err := a.AccessAPI1(KuaiShouRefundOrder, utils.Struct2MapByJson(param))
if err != nil {
return "", err
}
var result *RefundRes
if err := utils.Map2StructByJson(data, &result, false); err != nil {
return "", err
}
if result.Result != 1 {
return "", errors.New(result.ErrorMsg)
}
return result.RefundNo, nil
}
// RefundOrderDetail 查询退款订单详情
func (a *API) RefundOrderDetail(outRefundNo string) (*RefundInfo, error) {
data, err := a.AccessAPI1(KuaiShouRefundOrderDetail, map[string]interface{}{"out_refund_no": outRefundNo})
if err != nil {
return nil, err
}
var refundOrderDetail *RefundOrderDetail
if err := utils.Map2StructByJson(data, &refundOrderDetail, false); err != nil {
return nil, err
}
if refundOrderDetail.Result != 1 {
return nil, errors.New(refundOrderDetail.ErrorMsg)
}
var refundInfo *RefundInfo
if err := json.Unmarshal([]byte(refundOrderDetail.RefundInfo), &refundInfo); err != nil {
return nil, err
}
return refundInfo, nil
}
// PaySettleAccounts 结算用于确认一笔在途资金,将其转化为可提现资金。
// 结算规则
// 1、订单履约完成后发起结算结算周期为 订单到达核销状态订单状态为11或15满3天后可发起结算。核销状态通过订单同步接口 (opens new window)进行同步。
// 2、需要主动调用结算接口后才能进行后续资金的提现。
// 3、结算时小程序平台会收取整笔交易的平台服务费。若结算后发生退款则平台服务费不作退还。
func (a *API) PaySettleAccounts4Order(param *OrderSettleAccountParam) (string, error) {
data, err := a.AccessAPI1(KuaiShouGetSettleOrder, utils.Struct2MapByJson(param))
if err != nil {
return "", err
}
var settle *OrderSettleAccountRes
if err := utils.Map2StructByJson(data, &settle, false); err != nil {
return "", err
}
if settle.Result != 1 {
return "", err
}
return settle.SettleNo, nil
}
// QuerySettleInfo 查询结算信息
func (a *API) QuerySettleInfo(outSettleNo string) (*SettleInfo, error) {
data, err := a.AccessAPI1(KuaiShouQuerySettleOrder, map[string]interface{}{"out_settle_no": outSettleNo})
if err != nil {
return nil, err
}
var settle *QuerySettleInfoRes
if err := utils.Map2StructByJson(data, &settle, false); err != nil {
return nil, err
}
if settle.Result != 1 {
return nil, errors.New(settle.ErrorMsg)
}
if settle.SettleInfo == "" {
return nil, errors.New("数据查询为空")
}
var result *SettleInfo
if err := json.Unmarshal([]byte(settle.SettleInfo), result); err != nil {
return nil, err
}
return result, err
}
func (a *API) FullUrl(bashUrl string) string {
if a.accessToken == "" || a.expiresIn < time.Now().Unix() {
a.GetToken()