feat: add callback

This commit is contained in:
yanghao05
2025-04-14 21:15:24 +08:00
parent ea867f7261
commit 6e822e1a1b
7 changed files with 95 additions and 7 deletions

View File

@@ -1 +0,0 @@
package http

50
backend/app/http/pays.go Normal file
View File

@@ -0,0 +1,50 @@
package http
import (
"fmt"
"net/http"
"quyun/providers/wepay"
"github.com/go-pay/gopay"
"github.com/go-pay/gopay/wechat/v3"
"github.com/go-pay/util/js"
"github.com/gofiber/fiber/v3"
)
type pays struct {
wepay *wepay.Client
}
// Callback
// @Router /pay/callback [get]
func (ctl *pays) Callback(ctx fiber.Ctx) error {
body := ctx.Body()
si := &wechat.SignInfo{
HeaderTimestamp: ctx.Get(wechat.HeaderTimestamp),
HeaderNonce: ctx.Get(wechat.HeaderNonce),
HeaderSignature: ctx.Get(wechat.HeaderSignature),
HeaderSerial: ctx.Get(wechat.HeaderSerial),
SignBody: string(body),
}
notifyReq := &wechat.V3NotifyReq{SignInfo: si}
if err := js.UnmarshalBytes(body, notifyReq); err != nil {
return ctx.Status(http.StatusBadRequest).JSON(fiber.Map{"error": fmt.Sprintf("json unmarshal error:%v", err)})
}
// 获取微信平台证书
certMap := ctl.wepay.WxPublicKeyMap()
// 验证异步通知的签名
err := notifyReq.VerifySignByPKMap(certMap)
if err != nil {
return ctx.Status(http.StatusBadRequest).JSON(fiber.Map{"error": "Invalid signature"})
}
// TODO: add process order job
return ctx.Status(http.StatusOK).JSON(&wechat.V3NotifyRsp{
Code: gopay.SUCCESS,
Message: "成功",
})
}

View File

@@ -8,6 +8,7 @@ import (
"quyun/database/schemas/public/model" "quyun/database/schemas/public/model"
"quyun/providers/wepay" "quyun/providers/wepay"
"github.com/go-pay/gopay/wechat/v3"
"github.com/gofiber/fiber/v3" "github.com/gofiber/fiber/v3"
"github.com/gofiber/fiber/v3/log" "github.com/gofiber/fiber/v3/log"
"github.com/pkg/errors" "github.com/pkg/errors"
@@ -50,7 +51,7 @@ func (ctl *posts) Mine(ctx fiber.Ctx, pagination *requests.Pagination, query *Li
// Buy // Buy
// @Router /buy/:id [get] // @Router /buy/:id [get]
// @Bind id path // @Bind id path
func (ctl *posts) Buy(ctx fiber.Ctx, id int64) (*wepay.PrepayData, error) { func (ctl *posts) Buy(ctx fiber.Ctx, id int64) (*wechat.JSAPIPayParams, error) {
var userId int64 = 1 var userId int64 = 1
user, err := models.Users.GetByID(ctx.Context(), userId) user, err := models.Users.GetByID(ctx.Context(), userId)
@@ -80,5 +81,6 @@ func (ctl *posts) Buy(ctx fiber.Ctx, id int64) (*wepay.PrepayData, error) {
log.Errorf("wepay.V3TransactionJsapi err: %v", err) log.Errorf("wepay.V3TransactionJsapi err: %v", err)
return nil, errors.Wrap(err, "微信支付失败") return nil, errors.Wrap(err, "微信支付失败")
} }
return prePayResp, nil
return prePayResp.PaySignOfJSAPI()
} }

View File

@@ -1,6 +1,8 @@
package http package http
import ( import (
"quyun/providers/wepay"
"go.ipao.vip/atom" "go.ipao.vip/atom"
"go.ipao.vip/atom/container" "go.ipao.vip/atom/container"
"go.ipao.vip/atom/contracts" "go.ipao.vip/atom/contracts"
@@ -8,17 +10,23 @@ import (
) )
func Provide(opts ...opt.Option) error { func Provide(opts ...opt.Option) error {
if err := container.Container.Provide(func() (*posts, error) { if err := container.Container.Provide(func(
obj := &posts{} wepay *wepay.Client,
) (*posts, error) {
obj := &posts{
wepay: wepay,
}
return obj, nil return obj, nil
}); err != nil { }); err != nil {
return err return err
} }
if err := container.Container.Provide(func( if err := container.Container.Provide(func(
pays *pays,
posts *posts, posts *posts,
) (contracts.HttpRoute, error) { ) (contracts.HttpRoute, error) {
obj := &Routes{ obj := &Routes{
pays: pays,
posts: posts, posts: posts,
} }
if err := obj.Prepare(); err != nil { if err := obj.Prepare(); err != nil {

View File

@@ -14,6 +14,7 @@ import (
// @provider contracts.HttpRoute atom.GroupRoutes // @provider contracts.HttpRoute atom.GroupRoutes
type Routes struct { type Routes struct {
log *log.Entry `inject:"false"` log *log.Entry `inject:"false"`
pays *pays
posts *posts posts *posts
} }
@@ -27,8 +28,13 @@ func (r *Routes) Name() string {
} }
func (r *Routes) Register(router fiber.Router) { func (r *Routes) Register(router fiber.Router) {
// 注册路由组: pays
router.Get("/pay/callback", Func0(
r.pays.Callback,
))
// 注册路由组: posts // 注册路由组: posts
router.Get("/", DataFunc2( router.Get("/posts", DataFunc2(
r.posts.List, r.posts.List,
Query[requests.Pagination]("pagination"), Query[requests.Pagination]("pagination"),
Query[ListQuery]("query"), Query[ListQuery]("query"),
@@ -45,4 +51,9 @@ func (r *Routes) Register(router fiber.Router) {
Query[ListQuery]("query"), Query[ListQuery]("query"),
)) ))
router.Get("/buy/:id", DataFunc1(
r.posts.Buy,
PathParam[int64]("id"),
))
} }

View File

@@ -2,6 +2,7 @@ package wepay
import ( import (
"context" "context"
"crypto/rsa"
"encoding/json" "encoding/json"
"errors" "errors"
"time" "time"
@@ -55,11 +56,23 @@ func (c *Client) GetClient() *wechat.ClientV3 {
return c.payClient return c.payClient
} }
// WxPublicKeyMap
func (c *Client) WxPublicKeyMap() map[string]*rsa.PublicKey {
return c.payClient.WxPublicKeyMap()
}
type PrepayData struct { type PrepayData struct {
client *Client
AppID string `json:"app_id"` AppID string `json:"app_id"`
PrepayID string `json:"prepay_id"` PrepayID string `json:"prepay_id"`
} }
// PaySignOfJSAPI
func (pay *PrepayData) PaySignOfJSAPI() (*wechat.JSAPIPayParams, error) {
return pay.client.payClient.PaySignOfJSAPI(pay.AppID, pay.PrepayID)
}
func (c *Client) V3TransactionJsapi(ctx context.Context, f func(*BodyMap)) (*PrepayData, error) { func (c *Client) V3TransactionJsapi(ctx context.Context, f func(*BodyMap)) (*PrepayData, error) {
bm := NewBodyMap(c.config) bm := NewBodyMap(c.config)
f(bm) f(bm)
@@ -76,6 +89,8 @@ func (c *Client) V3TransactionJsapi(ctx context.Context, f func(*BodyMap)) (*Pre
} }
return &PrepayData{ return &PrepayData{
client: c,
AppID: c.config.AppID, AppID: c.config.AppID,
PrepayID: resp.Response.PrepayId, PrepayID: resp.Response.PrepayId,
}, nil }, nil

View File

@@ -45,8 +45,11 @@ func (s *WePayTestSuite) Test_PrePay() {
}) })
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(resp, ShouldNotBeNil) So(resp, ShouldNotBeNil)
s.T().Logf("prepay response: %+v", resp) s.T().Logf("prepay response: %+v", resp)
sign, err := resp.PaySignOfJSAPI()
So(err, ShouldBeNil)
s.T().Logf("Sign: %+v", sign)
}) })
}) })
} }