Some checks failed
Build docker and publish / linux (1.24.5) (push) Failing after 40s
feat(pay): 添加支付API基础结构 feat(miniapp): 创建支付测试小程序页面与配置 feat(wechatpay): 配置微信支付参数与证书 fix(guild): 修复成员列表查询条件 docs: 更新代码规范文档与需求文档 style: 统一前后端枚举显示与注释格式 refactor(admin): 重构用户奖励发放接口参数处理 test(title): 添加称号效果参数验证测试
90 lines
3.8 KiB
Go
90 lines
3.8 KiB
Go
package app
|
||
|
||
import (
|
||
"net/http"
|
||
|
||
"bindbox-game/configs"
|
||
"bindbox-game/internal/code"
|
||
"bindbox-game/internal/pkg/core"
|
||
"bindbox-game/internal/pkg/validation"
|
||
"bindbox-game/internal/pkg/pay"
|
||
"bindbox-game/internal/repository/mysql/model"
|
||
)
|
||
|
||
type jsapiPreorderRequest struct {
|
||
OrderNo string `json:"order_no" form:"order_no"`
|
||
OpenID string `json:"openid" form:"openid"`
|
||
}
|
||
type jsapiPreorderResponse struct {
|
||
TimeStamp string `json:"timeStamp"`
|
||
NonceStr string `json:"nonceStr"`
|
||
Package string `json:"package"`
|
||
SignType string `json:"signType"`
|
||
PaySign string `json:"paySign"`
|
||
}
|
||
|
||
// WechatJSAPIPreorder 小程序微信支付预下单并返回调起参数
|
||
// 入参:order_no(业务订单号)、openid(用户在小程序的openid)
|
||
// 返回:用于wx.requestPayment的参数(timeStamp/nonceStr/package/signType/paySign)
|
||
// 错误:参数绑定失败、配置缺失、订单不存在或状态不合法
|
||
func (h *handler) WechatJSAPIPreorder() core.HandlerFunc {
|
||
return func(ctx core.Context) {
|
||
req := new(jsapiPreorderRequest)
|
||
rsp := new(jsapiPreorderResponse)
|
||
if err := ctx.ShouldBindForm(req); err != nil {
|
||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
|
||
return
|
||
}
|
||
if ok, err := pay.ValidateConfig(); !ok {
|
||
ctx.AbortWithError(core.Error(http.StatusBadRequest, 140001, err.Error()))
|
||
return
|
||
}
|
||
c := configs.Get()
|
||
if req.OrderNo == "" || req.OpenID == "" {
|
||
ctx.AbortWithError(core.Error(http.StatusBadRequest, 140002, "order_no/openid required"))
|
||
return
|
||
}
|
||
// 查询订单并校验状态=1 待支付,归属当前用户
|
||
order, err := h.readDB.Orders.WithContext(ctx.RequestContext()).Where(h.readDB.Orders.OrderNo.Eq(req.OrderNo), h.readDB.Orders.UserID.Eq(int64(ctx.SessionUserInfo().Id)), h.readDB.Orders.Status.Eq(1)).First()
|
||
if err != nil || order == nil {
|
||
ctx.AbortWithError(core.Error(http.StatusBadRequest, 140006, "order not found or status invalid"))
|
||
return
|
||
}
|
||
wc, err := pay.NewWechatPayClient(ctx.RequestContext())
|
||
if err != nil {
|
||
ctx.AbortWithError(core.Error(http.StatusBadRequest, 140004, err.Error()))
|
||
return
|
||
}
|
||
prepayID, err := wc.JSAPIPrepay(ctx.RequestContext(), c.Wechat.AppID, c.WechatPay.MchID, "订单"+req.OrderNo, req.OrderNo, order.ActualAmount, req.OpenID, c.WechatPay.NotifyURL)
|
||
if err != nil {
|
||
ctx.AbortWithError(core.Error(http.StatusBadRequest, 140005, err.Error()))
|
||
return
|
||
}
|
||
pre := &model.PaymentPreorders{
|
||
OrderID: order.ID,
|
||
OrderNo: order.OrderNo,
|
||
OutTradeNo: order.OrderNo,
|
||
PrepayID: prepayID,
|
||
AmountTotal: order.ActualAmount,
|
||
PayerOpenid: req.OpenID,
|
||
NotifyURL: c.WechatPay.NotifyURL,
|
||
Status: "created",
|
||
}
|
||
if err := h.writeDB.PaymentPreorders.WithContext(ctx.RequestContext()).Omit(h.writeDB.PaymentPreorders.ExpiredAt).Create(pre); err == nil {
|
||
_, _ = h.writeDB.Orders.WithContext(ctx.RequestContext()).Where(h.readDB.Orders.ID.Eq(order.ID)).Updates(map[string]any{
|
||
h.readDB.Orders.PayPreorderID.ColumnName().String(): pre.ID,
|
||
})
|
||
}
|
||
ts, nonce, pkg, signType, paySign, err := pay.BuildJSAPIParams(c.Wechat.AppID, prepayID)
|
||
if err != nil {
|
||
ctx.AbortWithError(core.Error(http.StatusBadRequest, 140003, err.Error()))
|
||
return
|
||
}
|
||
rsp.TimeStamp = ts
|
||
rsp.NonceStr = nonce
|
||
rsp.Package = pkg
|
||
rsp.SignType = signType
|
||
rsp.PaySign = paySign
|
||
ctx.Payload(rsp)
|
||
}
|
||
} |