plugins/plugins/union_pay_redpack/internal/transform.go

194 lines
5.7 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 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"}
}