service/library/payclients/yeepaycli/client.go

247 lines
8.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package yeepaycli
import (
"context"
"encoding/json"
"fmt"
"github.com/yop-platform/yop-go-sdk/yop/client"
"github.com/yop-platform/yop-go-sdk/yop/constants"
"github.com/yop-platform/yop-go-sdk/yop/request"
yoputils "github.com/yop-platform/yop-go-sdk/yop/utils"
"net/http"
"service/bizcommon/util"
"service/library/configcenter"
"service/library/idgenerator"
"service/library/logger"
"time"
)
const (
YeepayWayH5 = "H5_PAY" // h5支付
)
const (
YeepayChannelWxpay = "WECHAT" // 易宝支付微信
YeepayChannelAlipay = "ALIPAY" // 易宝支付支付宝
)
const (
DefaultOrderTimeoutSeconds = 900 // 默认订单超时时间,单位: s
)
var defaultYeepayClient *YeepayClient
type YeepayClient struct {
client *client.YopClient
AppId string
ParentMerchantNo string // 父商编 系统商或平台商场景下为主商户商户编号,否则为收单商户编号
MerchantNo string // 子商编 收单商户商编
NotifyUrl string // 回调通知
PrivateKey string // 私钥
}
func GetDefaultYeepayClient() *YeepayClient {
return defaultYeepayClient
}
func Init(cfg *configcenter.YeepayClientConfig) {
cli := &client.YopClient{
Client: &http.Client{
Transport: http.DefaultTransport,
},
}
defaultYeepayClient = &YeepayClient{
client: cli,
AppId: cfg.Appid,
ParentMerchantNo: cfg.ParentMerchantNo,
MerchantNo: cfg.MerchantNo,
NotifyUrl: cfg.NotifyUrl,
PrivateKey: cfg.PrivateKey,
}
}
// 验签
type YeepayNotify struct {
ChannelOrderId string `json:"channelOrderId"`
OrderId string `json:"orderId"`
BankOrderId string `json:"bankOrderId"`
PaySuccessDate string `json:"paySuccessDate"`
Channel string `json:"channel"`
PayWay string `json:"payWay"`
UniqueOrderNo string `json:"uniqueOrderNo"`
OrderAmount string `json:"orderAmount"`
PayAmount string `json:"payAmount"`
PayerInfo string `json:"payerInfo"`
RealPayAmount string `json:"realPayAmount"`
ParentMerchantNo string `json:"parentMerchantNo"`
MerchantNo string `json:"merchantNo"`
Status string `json:"status"`
}
func (c *YeepayClient) ParseNotify(req *http.Request) (*YeepayNotify, error) {
if err := req.ParseForm(); err != nil {
logger.Error("Yeepay ParseForm fail, err: %v", err)
return nil, err
}
var (
response = req.Form.Get("response")
appKey = req.Form.Get("customerIdentification")
)
logger.Info("YeepayCallback notify, response: %v, appKey: %v", response, appKey)
content, err := yoputils.DecryptCallback(request.YOP_PLATFORM_PUBLIC_KEY, c.PrivateKey, response)
if err != nil {
logger.Error("Yeepay DecryptCallback fail, form: %v, err: %v", req.Form.Encode(), err)
return nil, err
}
notify := new(YeepayNotify)
err = json.Unmarshal([]byte(content), notify)
if err != nil {
logger.Error("Yeepay unmarshal fail, form: %v, content: %v, err: %v", req.Form.Encode(), util.ToJson(content), err)
return nil, err
}
logger.Info("Yeepay ParseNotify, %v", util.ToJson(notify))
return notify, nil
}
// 易宝支付 聚合支付
type AggPayParam struct {
Description string
OutTradeNo string // 商家订单id我们自己的订单id
TotalAmount int64 // 金额,单位:分
RedirectUrl string // 页面通知地址 支付成功后页面回调地址 如不指定页面回调地址,支付完成后会停留在易宝的支付成功页
PayWay string
PayChannel string
Ip string
}
type AggPayResp struct {
Code string `json:"code"`
Message string `json:"message"`
OrderId string `json:"orderId"`
UniqueOrderNo string `json:"uniqueOrderNo"`
BankOrderId string `json:"bankOrderId"`
PrePayTn string `json:"prePayTn"`
}
func (c *YeepayClient) AggPay(ctx context.Context, param *AggPayParam) (resp *AggPayResp, err error) {
req := request.NewYopRequest(constants.POST_HTTP_METHOD, "/rest/v1.0/aggpay/tutelage/pre-pay")
req.AppId = c.AppId
req.IsvPriKey = request.IsvPriKey{Value: c.PrivateKey, CertType: request.RSA2048}
req.AddParam("parentMerchantNo", c.ParentMerchantNo)
req.AddParam("merchantNo", c.MerchantNo)
req.AddParam("orderId", param.OutTradeNo)
req.AddParam("orderAmount", float64(param.TotalAmount)/100.0)
req.AddParam("expiredTime", time.Unix(time.Now().Unix()+DefaultOrderTimeoutSeconds, 0).Format("2006-01-02 15:04:05"))
req.AddParam("goodsName", param.Description)
req.AddParam("notifyUrl", c.NotifyUrl)
req.AddParam("payWay", param.PayWay)
req.AddParam("channel", param.PayChannel)
req.AddParam("scene", "OFFLINE")
req.AddParam("userIp", param.Ip)
if len(param.RedirectUrl) > 0 {
req.AddParam("redirectUrl", param.RedirectUrl)
}
respMeta, err := c.client.Request(req)
if err != nil {
logger.Error("yeepay AggPay fail, param: %v, respMeta: %v, err: %v", util.ToJson(req.Params), util.ToJson(respMeta), err)
return
}
resp = new(AggPayResp)
b, _ := json.Marshal(respMeta.Result)
_ = json.Unmarshal(b, resp)
logger.Info("yeepay AggPay param: %v, resp: %v", util.ToJson(req.Params), util.ToJson(resp))
return
}
// 退款
type RefundOneParam struct {
OutTradeNo string // 商家订单id我们自己的订单id
RefundAmount int64 // 退款金额,单位:分
RefundReason string // 退款理由
}
type RefundOneResp struct {
Code string `json:"code"`
Message string `json:"message"`
ParentMerchantNo string `json:"parentMerchantNo"`
MerchantNo string `json:"merchantNo"`
OrderId string `json:"orderId"`
RefundRequestId string `json:"refundRequestId"`
UniqueRefundNo string `json:"uniqueRefundNo"`
Status string `json:"status"`
RefundAmount string `json:"refundAmount"`
RefundRequestDate string `json:"refundRequestDate"`
RefundMerchantFee string `json:"refundMerchantFee"`
RefundAccountDetail string `json:"refundAccountDetail"`
RefundCsFinishDate string `json:"refundCsFinishDate"`
}
func (c *YeepayClient) RefundOne(ctx context.Context, param *RefundOneParam) (resp *RefundOneResp, refundRequestId string, err error) {
refundRequestId = idgenerator.GenYeepayRefundId()
req := request.NewYopRequest(constants.POST_HTTP_METHOD, "/rest/v1.0/trade/refund")
req.AppId = c.AppId
req.IsvPriKey = request.IsvPriKey{Value: c.PrivateKey, CertType: request.RSA2048}
req.AddParam("parentMerchantNo", c.ParentMerchantNo)
req.AddParam("merchantNo", c.MerchantNo)
req.AddParam("orderId", param.OutTradeNo)
req.AddParam("refundRequestId", refundRequestId)
req.AddParam("refundAmount", fmt.Sprintf("%.2f", float64(param.RefundAmount)/100.0))
respMeta, err := c.client.Request(req)
if err != nil {
logger.Error("yeepay RefundOne fail, param: %v, respMeta: %v, err: %v", util.ToJson(req.Params), util.ToJson(respMeta), err)
return
}
resp = new(RefundOneResp)
b, _ := json.Marshal(respMeta.Result)
_ = json.Unmarshal(b, resp)
logger.Info("yeepay RefundOne param: %v, resp: %v", util.ToJson(req.Params), util.ToJson(resp))
return
}
// 查询退款
type QueryRefundParam struct {
OutTradeNo string // 商家订单id我们自己的订单id
RefundRequestId string
}
type QueryRefundResp struct {
Code string `json:"code"`
Message string `json:"message"`
ParentMerchantNo string `json:"parentMerchantNo"`
MerchantNo string `json:"merchantNo"`
OrderId string `json:"orderId"`
RefundRequestId string `json:"refundRequestId"`
UniqueRefundNo string `json:"uniqueRefundNo"`
Status string `json:"status"`
RefundAmount string `json:"refundAmount"`
RefundRequestDate string `json:"refundRequestDate"`
RefundMerchantFee string `json:"refundMerchantFee"`
RefundAccountDetail string `json:"refundAccountDetail"`
RefundCsFinishDate string `json:"refundCsFinishDate"`
}
func (c *YeepayClient) QueryRefund(ctx context.Context, param *QueryRefundParam) (resp *QueryRefundResp, err error) {
req := request.NewYopRequest(constants.GET_HTTP_METHOD, "/rest/v1.0/trade/refund/query")
req.AppId = c.AppId
req.ServerRoot = request.SERVER_ROOT
req.IsvPriKey = request.IsvPriKey{Value: c.PrivateKey, CertType: request.RSA2048}
req.AddParam("parentMerchantNo", c.ParentMerchantNo)
req.AddParam("merchantNo", c.MerchantNo)
req.AddParam("orderId", param.OutTradeNo)
req.AddParam("refundRequestId", param.RefundRequestId)
respMeta, err := c.client.Request(req)
if err != nil {
logger.Error("yeepay RefundOne fail, param: %v, respMeta: %v, err: %v", util.ToJson(req.Params), util.ToJson(respMeta), err)
return
}
resp = new(QueryRefundResp)
b, _ := json.Marshal(respMeta.Result)
_ = json.Unmarshal(b, resp)
logger.Info("yeepay QueryRefund param: %v, resp: %v", util.ToJson(req.Params), util.ToJson(resp))
return
}