306 lines
7.3 KiB
Go
306 lines
7.3 KiB
Go
package mixrepoimpl
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"github.com/go-kratos/kratos/v2/log"
|
|
http2 "github.com/go-kratos/kratos/v2/transport/http"
|
|
"io"
|
|
"net/http"
|
|
"net/url"
|
|
"time"
|
|
err2 "voucher/api/err"
|
|
v1 "voucher/api/v1"
|
|
"voucher/internal/biz/bo"
|
|
"voucher/internal/biz/mixrepos"
|
|
"voucher/internal/biz/vo"
|
|
"voucher/internal/conf"
|
|
"voucher/internal/pkg/cmb"
|
|
"voucher/internal/pkg/helper"
|
|
"voucher/internal/pkg/request"
|
|
)
|
|
|
|
type CmbMixRepoImpl struct {
|
|
bc *conf.Bootstrap
|
|
}
|
|
|
|
func NewCmbMixRepoImpl(bc *conf.Bootstrap) mixrepos.CmbMixRepo {
|
|
return &CmbMixRepoImpl{bc: bc}
|
|
}
|
|
|
|
func (c *CmbMixRepoImpl) recordBody(ctx context.Context) {
|
|
|
|
httpRequest, ok := http2.RequestFromServerContext(ctx)
|
|
if !ok {
|
|
log.Errorf("read body not ok")
|
|
return
|
|
}
|
|
|
|
bodyBytes, err := io.ReadAll(httpRequest.Body)
|
|
if err != nil {
|
|
log.Errorf("read body not ok, %v", err)
|
|
return
|
|
}
|
|
|
|
log.Errorf("body %v", string(bodyBytes))
|
|
}
|
|
|
|
func (s *CmbMixRepoImpl) OrderVerify(ctx context.Context, req *v1.CmbRequest) (*v1.CmbOrderRequest, error) {
|
|
|
|
bizStr, err := s.Verify(ctx, req)
|
|
if err != nil {
|
|
return nil, err2.ErrorCmbVerifyFail(err.Error())
|
|
}
|
|
|
|
if len(bizStr) == 0 {
|
|
s.recordBody(ctx)
|
|
return nil, err2.ErrorCmbBizContentFail("业务参数获取异常,请检查参数是否正确传递")
|
|
}
|
|
|
|
var bizContent *v1.CmbOrderRequest
|
|
if err = json.Unmarshal([]byte(bizStr), &bizContent); err != nil {
|
|
return nil, err2.ErrorCmbBizContentFail(err.Error())
|
|
}
|
|
|
|
if err = bizContent.Validate(); err != nil {
|
|
return nil, err2.ErrorCmbBizContentFail(err.Error())
|
|
}
|
|
|
|
return bizContent, nil
|
|
}
|
|
|
|
func (s *CmbMixRepoImpl) QueryVerify(ctx context.Context, req *v1.CmbRequest) (*v1.CmbQueryRequest, error) {
|
|
|
|
bizStr, err := s.Verify(ctx, req)
|
|
if err != nil {
|
|
return nil, err2.ErrorCmbVerifyFail(err.Error())
|
|
}
|
|
|
|
if len(bizStr) == 0 {
|
|
s.recordBody(ctx)
|
|
return nil, err2.ErrorCmbBizContentFail("业务参数获取异常,请检查参数是否正确传递")
|
|
}
|
|
|
|
var bizContent *v1.CmbQueryRequest
|
|
if err = json.Unmarshal([]byte(bizStr), &bizContent); err != nil {
|
|
return nil, err2.ErrorCmbBizContentFail(err.Error())
|
|
}
|
|
|
|
if err = bizContent.Validate(); err != nil {
|
|
return nil, err2.ErrorCmbBizContentFail(err.Error())
|
|
}
|
|
|
|
return bizContent, nil
|
|
}
|
|
|
|
func (s *CmbMixRepoImpl) ProductQueryVerify(ctx context.Context, req *v1.CmbRequest) (*v1.CmbQueryProductRequest, error) {
|
|
|
|
bizStr, err := s.Verify(ctx, req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(bizStr) == 0 {
|
|
s.recordBody(ctx)
|
|
return nil, err2.ErrorCmbBizContentFail("业务参数获取异常,请检查参数是否正确传递")
|
|
}
|
|
|
|
var bizContent *v1.CmbQueryProductRequest
|
|
if err = json.Unmarshal([]byte(bizStr), &bizContent); err != nil {
|
|
return nil, err2.ErrorCmbBizContentFail(err.Error())
|
|
}
|
|
|
|
if err = bizContent.Validate(); err != nil {
|
|
return nil, err2.ErrorCmbBizContentFail(err.Error())
|
|
}
|
|
|
|
return bizContent, nil
|
|
}
|
|
|
|
func (s *CmbMixRepoImpl) Verify(_ context.Context, req *v1.CmbRequest) (string, error) {
|
|
|
|
str := cmb.SortStructStr(req)
|
|
|
|
b, err := cmb.VerifyBody(str, req.Sign, s.bc.Cmb.CmbSm2Puk)
|
|
if err != nil {
|
|
return "", err2.ErrorCmbVerifyFail(err.Error())
|
|
}
|
|
|
|
if !b {
|
|
return "", err2.ErrorCmbVerifyFail("签名验证失败")
|
|
}
|
|
|
|
bizBytes, err := cmb.DecryptBody(&cmb.Decrypts{EncryptBody: req.EncryptBody, PrivateKey: s.bc.Cmb.Sm2Prk})
|
|
if err != nil {
|
|
return "", err2.ErrorCmbBizContentDecryptFail(err.Error())
|
|
}
|
|
|
|
return string(bizBytes), nil
|
|
}
|
|
|
|
func (s *CmbMixRepoImpl) GetRequest(_ context.Context, reqBo *bo.CmbRequestBo) (*v1.CmbRequest, error) {
|
|
|
|
encryptBody, err := cmb.EncryptBody(&cmb.Encrypts{SoaPubKey: s.bc.Cmb.CmbSm2Puk, JsonParam: reqBo.BizContent})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
req := &v1.CmbRequest{
|
|
Mid: s.bc.Cmb.Mid,
|
|
Aid: s.bc.Cmb.Aid,
|
|
Date: time.Now().Format("20060102150405"),
|
|
Random: string(cmb.RandomBytes(16)),
|
|
KeyAlias: s.bc.Cmb.KeyAlias,
|
|
CmbKeyAlias: s.bc.Cmb.CmbKeyAlias,
|
|
EncryptBody: encryptBody,
|
|
Sign: "",
|
|
}
|
|
|
|
str := fmt.Sprintf("%s?%s", reqBo.FuncName, cmb.SortStructStr(req))
|
|
|
|
sign, err := cmb.SignBody(str, s.bc.Cmb.Sm2Prk)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
req.Sign = sign
|
|
|
|
return req, nil
|
|
}
|
|
|
|
func (s *CmbMixRepoImpl) GetMockRequest(_ context.Context, bizContent string) (*v1.CmbRequest, error) {
|
|
|
|
if len(s.bc.Cmb.Sm2Puk) == 0 {
|
|
return nil, errors.New("mock sm2 puk is empty")
|
|
}
|
|
|
|
if len(s.bc.Cmb.CmbSm2Pik) == 0 {
|
|
return nil, errors.New("mock cmb sm2 pik is empty")
|
|
}
|
|
|
|
encryptBody, err := cmb.EncryptBody(&cmb.Encrypts{SoaPubKey: s.bc.Cmb.Sm2Puk, JsonParam: bizContent})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
req := &v1.CmbRequest{
|
|
Mid: s.bc.Cmb.Mid,
|
|
Aid: s.bc.Cmb.Aid,
|
|
Date: time.Now().Format("20060102150405"),
|
|
Random: string(cmb.RandomBytes(16)),
|
|
KeyAlias: s.bc.Cmb.KeyAlias,
|
|
CmbKeyAlias: s.bc.Cmb.CmbKeyAlias,
|
|
EncryptBody: encryptBody,
|
|
Sign: "",
|
|
}
|
|
|
|
sign, err := cmb.SignBody(cmb.SortStructStr(req), s.bc.Cmb.CmbSm2Pik)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
req.Sign = sign
|
|
|
|
return req, nil
|
|
}
|
|
|
|
func (s *CmbMixRepoImpl) VerifyResponse(_ context.Context, req *v1.CmbReply) error {
|
|
|
|
str := cmb.SortStructStr(req)
|
|
|
|
b, err := cmb.VerifyBody(str, req.Sign, s.bc.Cmb.CmbSm2Puk)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if !b {
|
|
return errors.New("签名验证失败")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *CmbMixRepoImpl) GetResponse(_ context.Context, reqBo *bo.CmbResponseBo) (*v1.CmbReply, error) {
|
|
|
|
reply := &v1.CmbReply{
|
|
RespCode: reqBo.RespCode,
|
|
RespMsg: reqBo.RespMsg,
|
|
Date: time.Now().Format("20060102150405"),
|
|
KeyAlias: s.bc.Cmb.KeyAlias,
|
|
CmbKeyAlias: s.bc.Cmb.CmbKeyAlias,
|
|
EncryptBody: "",
|
|
Sign: "",
|
|
}
|
|
|
|
if len(reqBo.BizContent) > 0 {
|
|
encryptBody, err := cmb.EncryptBody(&cmb.Encrypts{SoaPubKey: s.bc.Cmb.CmbSm2Puk, JsonParam: reqBo.BizContent})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
reply.EncryptBody = encryptBody
|
|
}
|
|
|
|
sign, err := cmb.SignBody(cmb.SortStructStr(reply), s.bc.Cmb.Sm2Prk)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
reply.Sign = sign
|
|
|
|
return reply, nil
|
|
}
|
|
|
|
func (s *CmbMixRepoImpl) Request(ctx context.Context, req *v1.CmbRequest, uri string) (*v1.CmbReply, error) {
|
|
|
|
kvRows := helper.SortStructFieldsByKey(req)
|
|
|
|
uv := url.Values{}
|
|
|
|
for _, kv := range kvRows {
|
|
uv.Set(kv.Key, fmt.Sprintf("%v", kv.Value))
|
|
}
|
|
|
|
h := http.Header{
|
|
"Content-Type": []string{"application/x-www-form-urlencoded"},
|
|
}
|
|
|
|
r := uri + "?" + uv.Encode()
|
|
|
|
_, bodyBytes, err := request.Post(ctx, r, nil, request.WithHeaders(h))
|
|
if err != nil {
|
|
log.Errorf("请求掌上生活报错,url:%s,err:%v", r, err)
|
|
return nil, err
|
|
}
|
|
|
|
log.Warnf("请求掌上生活响应结果,url:%s,bodyBytes:%s", r, string(bodyBytes))
|
|
|
|
var response *v1.CmbReply
|
|
if err = json.Unmarshal(bodyBytes, &response); err != nil {
|
|
log.Errorf("请求掌上生活返回数据解析报错:%s", err.Error())
|
|
return nil, err
|
|
}
|
|
|
|
if response.RespCode != vo.CmbResponseStatusSuccess.GetValue() {
|
|
log.Errorf("请求掌上生活返回报错:%s", r, response.RespMsg)
|
|
return nil, fmt.Errorf(response.RespMsg)
|
|
}
|
|
|
|
return response, nil
|
|
}
|
|
|
|
func (s *CmbMixRepoImpl) Decrypt(_ context.Context, encryptBody string) (string, error) {
|
|
|
|
if len(s.bc.Cmb.CmbSm2Pik) == 0 {
|
|
return "", errors.New("mock CmbSm2Pik is empty")
|
|
}
|
|
|
|
rs, err := cmb.DecryptBody(&cmb.Decrypts{EncryptBody: encryptBody, PrivateKey: s.bc.Cmb.CmbSm2Pik})
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return string(rs), nil
|
|
}
|