voucher/internal/data/wechatrepoimpl/cpn.go

284 lines
6.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 wechatrepoimpl
import (
"context"
"encoding/json"
"fmt"
"github.com/go-kratos/kratos/v2/log"
"github.com/wechatpay-apiv3/wechatpay-go/core"
"github.com/wechatpay-apiv3/wechatpay-go/services/cashcoupons"
"io"
"net/http"
"voucher/internal/biz/bo"
"voucher/internal/biz/vo"
"voucher/internal/biz/wechatrepo"
"voucher/internal/conf"
"voucher/internal/data"
"voucher/internal/pkg/request"
)
type CpnRepoImpl struct {
bc *conf.Bootstrap
Server data.Server
}
func NewCpnRepoImpl(bc *conf.Bootstrap) (wechatrepo.WechatCpnRepo, error) {
server := data.Server{
MchID: bc.Wechat.MchID,
MchCertificateSerialNumber: bc.Wechat.MchCertificateSerialNumber,
}
if err := server.Validate(); err != nil {
return nil, err
}
return &CpnRepoImpl{bc: bc, Server: server}, nil
}
func (c *CpnRepoImpl) Order(ctx context.Context, order *bo.OrderBo) (string, error) {
req := cashcoupons.SendCouponRequest{
OutRequestNo: core.String(order.OrderNo),
// 微信为发券方商户分配的公众账号ID接口传入的所有appid应该为公众号的appid在mp.weixin.qq.com申请的不能为APP的appid在open.weixin.qq.com申请的
Appid: core.String(order.AppID),
Openid: core.String(order.Account),
StockId: core.String(order.BatchNo),
StockCreatorMchid: core.String(order.MerchantNo),
}
client, err := data.GetClient(ctx, c.Server)
if err != nil {
return "", err
}
svc := cashcoupons.CouponApiService{Client: client}
resp, result, err := svc.SendCoupon(ctx, req)
if err != nil {
bodyBytes, err := io.ReadAll(result.Response.Body)
if err != nil {
return "", err
}
log.Errorf("请求微信返回错误:%s", string(bodyBytes))
if err = json.Unmarshal(bodyBytes, &ErrBody); err != nil {
return "", err
}
return "", fmt.Errorf(ErrBody.Message)
}
if result.Response.StatusCode != CodeSuccess {
return "", fmt.Errorf("请求错误,code:%s", result.Response.Status)
}
return *resp.CouponId, nil
}
func (c *CpnRepoImpl) Query(ctx context.Context, orderWechat *bo.OrderBo) (vo.OrderStatus, error) {
req := cashcoupons.QueryCouponRequest{
CouponId: core.String(orderWechat.VoucherNo),
Appid: core.String(orderWechat.AppID),
Openid: core.String(orderWechat.Account),
}
client, err := data.GetClient(ctx, c.Server)
if err != nil {
return 0, err
}
svc := cashcoupons.CouponApiService{Client: client}
resp, result, err := svc.QueryCoupon(ctx, req)
if err != nil {
bodyBytes, err := io.ReadAll(result.Response.Body)
if err != nil {
return 0, err
}
log.Errorf("请求微信返回错误:%s", string(bodyBytes))
if err = json.Unmarshal(bodyBytes, &ErrBody); err != nil {
return 0, err
}
return 0, fmt.Errorf("微信返回错误:%s", ErrBody.Message)
}
if result.Response.StatusCode != CodeSuccess {
return 0, fmt.Errorf("微信返回错误 Response StatusCode[%s]", result.Response.StatusCode)
}
return CpnStatus(*resp.Status).GetStatus()
}
func (c *CpnRepoImpl) QueryProduct(ctx context.Context, stockCreatorMchId, stockId string) (*cashcoupons.Stock, error) {
client, err := data.GetClient(ctx, c.Server)
if err != nil {
return nil, err
}
svc := cashcoupons.StockApiService{Client: client}
response, result, err := svc.QueryStock(ctx, cashcoupons.QueryStockRequest{
StockId: core.String(stockId),
StockCreatorMchid: core.String(stockCreatorMchId),
})
if err != nil {
bodyBytes, err := io.ReadAll(result.Response.Body)
if err != nil {
return nil, err
}
if err = json.Unmarshal(bodyBytes, &ErrBody); err != nil {
return nil, err
}
return nil, fmt.Errorf("微信返回错误:%s", ErrBody.Message)
}
if result.Response.StatusCode != CodeSuccess {
return nil, fmt.Errorf("查询活动微信返回错误 Response StatusCode[%s]", result.Response.StatusCode)
}
return response, nil
}
func (c *CpnRepoImpl) QueryCallback(ctx context.Context, mchId, mchCertNo string) (*cashcoupons.Callback, error) {
server := data.Server{
MchID: mchId,
MchCertificateSerialNumber: mchCertNo,
}
if err := server.Validate(); err != nil {
return nil, err
}
client, err := data.GetClient(ctx, server)
if err != nil {
return nil, err
}
svc := cashcoupons.CallBackUrlApiService{Client: client}
response, result, err := svc.QueryCallback(ctx, cashcoupons.QueryCallbackRequest{
Mchid: core.String(mchId),
})
if err != nil {
log.Errorf("请求微信返回错误:%s", err.Error())
bodyBytes, err := io.ReadAll(result.Response.Body)
if err != nil {
return nil, err
}
if err = json.Unmarshal(bodyBytes, &ErrBody); err != nil {
return nil, err
}
return nil, fmt.Errorf("微信返回错误:%s", ErrBody.Message)
}
if result.Response.StatusCode != CodeSuccess {
return nil, fmt.Errorf("微信返回错误tatus[%s]", result.Response.Status)
}
return response, nil
}
func (c *CpnRepoImpl) SetCallback(ctx context.Context, mchId, mchCertNo, url string) (*cashcoupons.SetCallbackResponse, error) {
server := data.Server{
MchID: mchId,
MchCertificateSerialNumber: mchCertNo,
}
if err := server.Validate(); err != nil {
return nil, err
}
client, err := data.GetClient(ctx, server)
if err != nil {
return nil, err
}
svc := cashcoupons.CallBackUrlApiService{Client: client}
response, result, err := svc.SetCallback(ctx, cashcoupons.SetCallbackRequest{
Mchid: core.String(mchId),
NotifyUrl: core.String(url),
Switch: core.Bool(true),
})
if err != nil {
log.Errorf("请求微信返回错误:%s", err.Error())
bodyBytes, err := io.ReadAll(result.Response.Body)
if err != nil {
return nil, err
}
if err = json.Unmarshal(bodyBytes, &ErrBody); err != nil {
return nil, err
}
return nil, fmt.Errorf("微信返回错误:%s", ErrBody.Message)
}
if result.Response.StatusCode != CodeSuccess {
return nil, fmt.Errorf("微信返回错误tatus[%s]", result.Response.Status)
}
return response, nil
}
func (c *CpnRepoImpl) RegisterNotifyTag(ctx context.Context, stockID string) error {
// 注册“刚哥那边”回调中心tag,一个批次只能注册一次消费时根据不同的tag消费(区分测试/正式注册tag处理)
h := http.Header{
"Content-Type": []string{"application/json"},
}
b := struct {
TagName string `json:"tag_name"`
StockID string `json:"stock_id"`
}{
TagName: c.bc.WechatNotifyMQ.Tag,
StockID: stockID,
}
body, err := json.Marshal(b)
if err != nil {
return err
}
isSuccess := func(code int) bool {
return code == http.StatusOK
}
_, _, err = request.Post(
ctx,
c.bc.WechatNotifyMQ.RegisterTagUrl,
body,
request.WithHeaders(h),
request.WithStatusCodeFunc(isSuccess),
)
if err != nil {
return err
}
return nil
}