Files
pay/internal/handler/page.go
T
wangjia 6da6964451 初始提交:岩美 pay 收款服务(支付宝当面付 + 多商户多渠道架构)
- Go/Gin/GORM + 纯 Go SQLite(无 cgo)
- Channel 多渠道接口:支付宝当面付(precreate)/电脑网站支付(page.pay) 已实现,微信占位
- 多商户 merchants 表,回调验签+金额核对+幂等+查单兜底
- 收款页/结果页/二维码端点;docs/ 设计文档与部署 Runbook
- 密钥走环境变量/Bitwarden,不入库

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 07:21:48 +08:00

66 lines
1.7 KiB
Go

package handler
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/skip2/go-qrcode"
"gorm.io/gorm"
"github.com/wangjia/pay/internal/model"
"github.com/wangjia/pay/internal/util"
)
type PageHandler struct {
db *gorm.DB
webDir string
}
func NewPageHandler(db *gorm.DB, webDir string) *PageHandler {
return &PageHandler{db: db, webDir: webDir}
}
// PayPage GET / —— 收款页。
func (h *PageHandler) PayPage(c *gin.Context) {
c.File(h.webDir + "/pay.html")
}
// ResultPage GET /result —— 支付结果页(return_url 落地)。
func (h *PageHandler) ResultPage(c *gin.Context) {
c.File(h.webDir + "/result.html")
}
// QRCode GET /qrcode?text=xxx —— 把任意字符串渲染成二维码 PNG(用于展示支付宝扫码码串)。
func (h *PageHandler) QRCode(c *gin.Context) {
text := c.Query("text")
if text == "" {
util.RespondError(c, http.StatusBadRequest, "bad_request", "缺少 text 参数")
return
}
png, err := qrcode.Encode(text, qrcode.Medium, 256)
if err != nil {
util.RespondError(c, http.StatusInternalServerError, "qr_failed", err.Error())
return
}
c.Data(http.StatusOK, "image/png", png)
}
// ListProducts GET /api/v1/products —— 上架套餐列表(金额来自服务端)。
func (h *PageHandler) ListProducts(c *gin.Context) {
var products []model.Product
if err := h.db.Where("active = ?", true).Order("sort asc, id asc").Find(&products).Error; err != nil {
util.RespondError(c, http.StatusInternalServerError, "list_failed", err.Error())
return
}
out := make([]gin.H, 0, len(products))
for _, p := range products {
out = append(out, gin.H{
"id": p.ID,
"name": p.Name,
"description": p.Description,
"price": p.Price,
})
}
util.RespondSuccess(c, out)
}