194 lines
5.7 KiB
Go
194 lines
5.7 KiB
Go
package internal
|
||
|
||
import (
|
||
"context"
|
||
"encoding/json"
|
||
"fmt"
|
||
"gitea.cdlsxd.cn/sdk/plugin/proto"
|
||
sdkutils "gitea.cdlsxd.cn/sdk/plugin/utils"
|
||
"github.com/go-playground/validator/v10"
|
||
"net/http"
|
||
"plugins/union_pay_redpack/internal/po"
|
||
"plugins/union_pay_redpack/internal/vo"
|
||
"plugins/utils/request"
|
||
"plugins/utils/union_pay"
|
||
"time"
|
||
)
|
||
|
||
type Config struct {
|
||
AppId string `validate:"required" json:"app_id"`
|
||
ChNlId string `validate:"required" json:"chnlId"` // 渠道方代码
|
||
IV string `validate:"required" json:"iv"` // 加密密钥
|
||
KEY string `validate:"required" json:"key"` // 加密密钥
|
||
Prk string `validate:"required" json:"prk"` // 私钥
|
||
Npk string `validate:"required" json:"npk"` // 回调公钥
|
||
|
||
PointId string `validate:"required" json:"point_id"` // 积分ID-积分类别代码,41开头的16位数字
|
||
InsAcctId string `validate:"required" json:"ins_acct_id"` // 机构账户代码
|
||
}
|
||
|
||
func (c *Config) validate() error {
|
||
err := validator.New().Struct(c)
|
||
if err != nil {
|
||
for _, err = range err.(validator.ValidationErrors) {
|
||
return proto.ErrorConfigFail(fmt.Sprintf("配置参数有误:%s", err.Error()))
|
||
}
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func transConfig(config []byte) (*Config, error) {
|
||
var c Config
|
||
if err := json.Unmarshal(config, &c); err != nil {
|
||
return nil, proto.ErrorConfigFail(fmt.Sprintf("配置参数有误:%s", err.Error()))
|
||
}
|
||
if err := c.validate(); err != nil {
|
||
return nil, err
|
||
}
|
||
return &c, nil
|
||
}
|
||
|
||
func (c *Config) headers(bizMethod string, req po.Req) http.Header {
|
||
h := make(http.Header)
|
||
h.Add("Content-type", vo.ContentType)
|
||
h.Add("version", vo.Version)
|
||
h.Add("appType", vo.AppType)
|
||
h.Add("signMethod", vo.SignMethod)
|
||
|
||
h.Add("appId", c.AppId)
|
||
h.Add("bizMethod", bizMethod)
|
||
|
||
h.Add("reqId", req.GetReId())
|
||
|
||
now := time.Now()
|
||
milliseconds := now.Unix()*1000 + int64(now.Nanosecond())/1e6
|
||
h.Add("reqTs", fmt.Sprintf("%d", milliseconds))
|
||
|
||
rehash := union_pay.Sha(vo.Version, c.AppId, bizMethod, req.GetReId(), string(req.ToJson()))
|
||
signValue, err := union_pay.Sign(rehash, []byte(sdkutils.NewPrivate().Build(c.Prk)))
|
||
if err != nil {
|
||
return nil
|
||
}
|
||
h.Add("sign", signValue)
|
||
return h
|
||
}
|
||
|
||
func (c *Config) Request(ctx context.Context, req po.Req, method, bizMethod string) (http.Header, []byte, error) {
|
||
respHeader, respBody, err := request.Post(
|
||
ctx,
|
||
fmt.Sprintf("%s%s", baseUri, method),
|
||
req.ToJson(),
|
||
request.WithHeaders(c.headers(bizMethod, req)),
|
||
request.WithTimeout(15*time.Second),
|
||
request.WithStatusCodeFunc(func(code int) bool {
|
||
return code == http.StatusOK
|
||
}),
|
||
)
|
||
if err != nil {
|
||
return nil, nil, proto.ErrorRequestFail(err.Error())
|
||
}
|
||
return respHeader, respBody, nil
|
||
}
|
||
|
||
func (c *Config) orderReq(in *proto.OrderRequest) (*po.OrderReq, error) {
|
||
type OrderExtra struct {
|
||
TransDtTm string `json:"transDtTm"` // 交易日期时间
|
||
ValidEndDtTm string `json:"validEndDtTm"` // 有效截止时间
|
||
TransDigest string `json:"transDigest"` // 交易摘要
|
||
}
|
||
var e OrderExtra
|
||
if err := json.Unmarshal(in.Order.Extra, &e); err != nil {
|
||
return nil, fmt.Errorf("order extra fail: %v", err)
|
||
}
|
||
|
||
mobile, err := union_pay.Encrypt([]byte(in.Order.Account), []byte(c.KEY), []byte(c.IV))
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
point := int(in.Order.Amount * 100)
|
||
return &po.OrderReq{
|
||
ChNlId: c.ChNlId,
|
||
AccessId: vo.AccessId,
|
||
TransSeq: in.Order.OrderNo,
|
||
TransDtTm: e.TransDtTm,
|
||
InsAcctTp: vo.InsAcctTp,
|
||
InsAcctId: c.InsAcctId,
|
||
AcctEntityTp: vo.AcctEntityTp,
|
||
Mobile: mobile,
|
||
PointTp: vo.PointTp,
|
||
PointId: c.PointId,
|
||
PointAt: fmt.Sprintf("%d", point),
|
||
DelayIn: vo.DelayIn,
|
||
TempIn: vo.TempIn,
|
||
InOutTransFlag: vo.InOutTransFlag,
|
||
TransDigest: e.TransDigest,
|
||
ValidEndDtTm: e.ValidEndDtTm,
|
||
}, nil
|
||
}
|
||
|
||
func orderResp(request *proto.OrderRequest, resp po.OrderResp) *proto.OrderResponse {
|
||
data, _ := json.Marshal(resp)
|
||
result := &proto.Result{
|
||
OrderNo: request.Order.OrderNo,
|
||
TradeNo: "",
|
||
Message: resp.Msg,
|
||
Data: data,
|
||
}
|
||
if !resp.Code.IsSuccess() {
|
||
result.Status = proto.Status_FAIL
|
||
result.Message = resp.GetMsg()
|
||
} else {
|
||
result.Status = proto.Status_ING
|
||
}
|
||
return &proto.OrderResponse{Result: result}
|
||
}
|
||
|
||
func (c *Config) queryReq(in *proto.QueryRequest, chNlId string) (*po.QueryReq, error) {
|
||
type OrderExtra struct {
|
||
TransSeq string `json:"transSeq"` // 当前交易号
|
||
TransDtTm string `json:"transDtTm"` // 交易日期时间
|
||
OrigTransDtTm string `json:"origTransDtTm"` // 原交易日期时间
|
||
}
|
||
var e OrderExtra
|
||
if err := json.Unmarshal(in.Order.Extra, &e); err != nil {
|
||
return nil, fmt.Errorf("order extra fail: %v", err)
|
||
}
|
||
mobile, err := union_pay.Encrypt([]byte(in.Order.Account), []byte(c.KEY), []byte(c.IV))
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return &po.QueryReq{
|
||
ChNlId: chNlId,
|
||
TransSeq: e.TransSeq, // 当前交易号
|
||
TransDtTm: e.TransDtTm, // 交易日期时间
|
||
OrigTransDtTm: e.OrigTransDtTm, // 原交易流水号
|
||
OrigTransSeq: in.Order.OrderNo, // 原交易流水号
|
||
AcctEntityTp: vo.AcctEntityTp,
|
||
Mobile: mobile,
|
||
}, nil
|
||
}
|
||
|
||
func queryResp(request *proto.QueryRequest, resp po.QueryResp) *proto.QueryResponse {
|
||
data, _ := json.Marshal(resp)
|
||
result := &proto.Result{
|
||
OrderNo: request.Order.OrderNo,
|
||
TradeNo: request.Order.TradeNo,
|
||
Status: resp.AcquireSt.GetOrderStatus(),
|
||
Message: resp.GetMsg(),
|
||
Data: data,
|
||
}
|
||
return &proto.QueryResponse{Result: result}
|
||
}
|
||
|
||
func notifyResp() *proto.NotifyResponse {
|
||
result := &proto.Result{
|
||
Status: proto.Status_ING,
|
||
OrderNo: "",
|
||
TradeNo: "",
|
||
Message: "无回调通知",
|
||
Data: nil,
|
||
Extra: nil,
|
||
}
|
||
return &proto.NotifyResponse{Result: result, Return: "success"}
|
||
}
|