mirror of
https://github.com/yangjian102621/geekai.git
synced 2025-09-19 01:36:38 +08:00
payment for mobile page is ready
This commit is contained in:
parent
4976b967e7
commit
16ac57ced3
@ -71,6 +71,14 @@ TikaHost = "http://tika:9998"
|
|||||||
AccessToken = "xxl-job-api-token" # 执行器 API 通信 token
|
AccessToken = "xxl-job-api-token" # 执行器 API 通信 token
|
||||||
RegistryKey = "chatgpt-plus" # 任务注册 key
|
RegistryKey = "chatgpt-plus" # 任务注册 key
|
||||||
|
|
||||||
|
[SmtpConfig] # 注意,阿里云服务器禁用了25号端口,请使用 465 端口,并开启 TLS 连接
|
||||||
|
UseTls = false
|
||||||
|
Host = "smtp.163.com"
|
||||||
|
Port = 25
|
||||||
|
AppName = "极客学长"
|
||||||
|
From = "test@163.com" # 发件邮箱人地址
|
||||||
|
Password = "" #邮箱 stmp 服务授权码
|
||||||
|
|
||||||
[AlipayConfig]
|
[AlipayConfig]
|
||||||
Enabled = false # 启用支付宝支付通道
|
Enabled = false # 启用支付宝支付通道
|
||||||
SandBox = false # 是否启用沙盒模式
|
SandBox = false # 是否启用沙盒模式
|
||||||
@ -80,31 +88,12 @@ TikaHost = "http://tika:9998"
|
|||||||
PublicKey = "certs/alipay/appPublicCert.crt" # 应用公钥证书
|
PublicKey = "certs/alipay/appPublicCert.crt" # 应用公钥证书
|
||||||
AlipayPublicKey = "certs/alipay/alipayPublicCert.crt" # 支付宝公钥证书
|
AlipayPublicKey = "certs/alipay/alipayPublicCert.crt" # 支付宝公钥证书
|
||||||
RootCert = "certs/alipay/alipayRootCert.crt" # 支付宝根证书
|
RootCert = "certs/alipay/alipayRootCert.crt" # 支付宝根证书
|
||||||
NotifyURL = "https://ai.r9it.com/api/payment/alipay/notify" # 支付异步回调地址
|
|
||||||
|
|
||||||
[HuPiPayConfig]
|
[HuPiPayConfig]
|
||||||
Enabled = false
|
Enabled = false
|
||||||
Name = "wechat"
|
|
||||||
AppId = ""
|
AppId = ""
|
||||||
AppSecret = ""
|
AppSecret = ""
|
||||||
ApiURL = "https://api.xunhupay.com"
|
ApiURL = "https://api.xunhupay.com"
|
||||||
NotifyURL = "https://ai.r9it.com/api/payment/hupipay/notify"
|
|
||||||
|
|
||||||
[SmtpConfig] # 注意,阿里云服务器禁用了25号端口,请使用 465 端口,并开启 TLS 连接
|
|
||||||
UseTls = false
|
|
||||||
Host = "smtp.163.com"
|
|
||||||
Port = 25
|
|
||||||
AppName = "极客学长"
|
|
||||||
From = "test@163.com" # 发件邮箱人地址
|
|
||||||
Password = "" #邮箱 stmp 服务授权码
|
|
||||||
|
|
||||||
[JPayConfig] # PayJs 支付配置
|
|
||||||
Enabled = false
|
|
||||||
Name = "wechat" # 请不要改动
|
|
||||||
AppId = "" # 商户 ID
|
|
||||||
PrivateKey = "" # 秘钥
|
|
||||||
ApiURL = "https://payjs.cn"
|
|
||||||
NotifyURL = "https://ai.r9it.com/api/payment/payjs/notify" # 异步回调地址,域名改成你自己的
|
|
||||||
|
|
||||||
# 微信商户支付
|
# 微信商户支付
|
||||||
[WechatPayConfig]
|
[WechatPayConfig]
|
||||||
@ -114,6 +103,11 @@ TikaHost = "http://tika:9998"
|
|||||||
SerialNo = "" # API 证书序列号
|
SerialNo = "" # API 证书序列号
|
||||||
PrivateKey = "certs/alipay/privateKey.txt" # API 证书私钥文件路径,跟支付宝一样,把私钥文件拷贝到对应的路径,证书路径要映射到容器内
|
PrivateKey = "certs/alipay/privateKey.txt" # API 证书私钥文件路径,跟支付宝一样,把私钥文件拷贝到对应的路径,证书路径要映射到容器内
|
||||||
ApiV3Key = "" # APIV3 私钥,这个是你自己在微信支付平台设置的
|
ApiV3Key = "" # APIV3 私钥,这个是你自己在微信支付平台设置的
|
||||||
NotifyURL = "https://ai.r9it.com/api/payment/wechat/notify" # 支付成功异步回调地址,域名改成自己的
|
|
||||||
ReturnURL = "" # 支付成功同步回调地址
|
|
||||||
|
|
||||||
|
# 易支付
|
||||||
|
[GeekPayConfig]
|
||||||
|
Enabled = true
|
||||||
|
AppId = "" # 商户ID
|
||||||
|
PrivateKey = "" # 商户私钥
|
||||||
|
ApiURL = "https://pay.geekai.cn"
|
||||||
|
Methods = ["alipay", "wxpay", "qqpay", "jdpay", "douyin", "paypal"] # 支持的支付方式
|
||||||
|
@ -58,6 +58,7 @@ type AlipayConfig struct {
|
|||||||
AlipayPublicKey string // 支付宝公钥文件路径
|
AlipayPublicKey string // 支付宝公钥文件路径
|
||||||
RootCert string // Root 秘钥路径
|
RootCert string // Root 秘钥路径
|
||||||
NotifyURL string // 异步通知地址
|
NotifyURL string // 异步通知地址
|
||||||
|
ReturnURL string // 同步通知地址
|
||||||
}
|
}
|
||||||
|
|
||||||
type WechatPayConfig struct {
|
type WechatPayConfig struct {
|
||||||
@ -76,6 +77,7 @@ type HuPiPayConfig struct { //虎皮椒第四方支付配置
|
|||||||
AppSecret string // app 密钥
|
AppSecret string // app 密钥
|
||||||
ApiURL string // 支付网关
|
ApiURL string // 支付网关
|
||||||
NotifyURL string // 异步通知地址
|
NotifyURL string // 异步通知地址
|
||||||
|
ReturnURL string // 同步通知地址
|
||||||
}
|
}
|
||||||
|
|
||||||
// GeekPayConfig GEEK支付配置
|
// GeekPayConfig GEEK支付配置
|
||||||
@ -85,6 +87,7 @@ type GeekPayConfig struct {
|
|||||||
PrivateKey string // 私钥
|
PrivateKey string // 私钥
|
||||||
ApiURL string // API 网关
|
ApiURL string // API 网关
|
||||||
NotifyURL string // 异步通知地址
|
NotifyURL string // 异步通知地址
|
||||||
|
ReturnURL string // 同步通知地址
|
||||||
Methods []string // 支付方式
|
Methods []string // 支付方式
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,14 +73,21 @@ func NewPaymentHandler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *PaymentHandler) Pay(c *gin.Context) {
|
func (h *PaymentHandler) Pay(c *gin.Context) {
|
||||||
payWay := c.Query("pay_way")
|
var data struct {
|
||||||
payType := c.Query("pay_type")
|
PayWay string `json:"pay_way"`
|
||||||
productId := c.Query("product_id")
|
PayType string `json:"pay_type"`
|
||||||
device := c.Query("device")
|
ProductId int `json:"product_id"`
|
||||||
userId := c.Query("user_id")
|
UserId int `json:"user_id"`
|
||||||
|
Device string `json:"device"`
|
||||||
|
Host string `json:"host"`
|
||||||
|
}
|
||||||
|
if err := c.ShouldBindJSON(&data); err != nil {
|
||||||
|
resp.ERROR(c, types.InvalidArgs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var product model.Product
|
var product model.Product
|
||||||
err := h.DB.Where("id", productId).First(&product).Error
|
err := h.DB.Where("id", data.ProductId).First(&product).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.ERROR(c, "Product not found")
|
resp.ERROR(c, "Product not found")
|
||||||
return
|
return
|
||||||
@ -92,36 +99,73 @@ func (h *PaymentHandler) Pay(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
var user model.User
|
var user model.User
|
||||||
err = h.DB.Where("id", userId).First(&user).Error
|
err = h.DB.Where("id", data.UserId).First(&user).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.NotAuth(c)
|
resp.NotAuth(c)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
amount, _ := decimal.NewFromFloat(product.Price).Sub(decimal.NewFromFloat(product.Discount)).Float64()
|
amount, _ := decimal.NewFromFloat(product.Price).Sub(decimal.NewFromFloat(product.Discount)).Float64()
|
||||||
var payURL string
|
var payURL, returnURL, notifyURL string
|
||||||
if payWay == "alipay" { // 支付宝
|
switch data.PayWay {
|
||||||
returnURL := fmt.Sprintf("%s/payReturn", utils.GetBaseURL(h.App.Config.AlipayConfig.NotifyURL))
|
case "alipay":
|
||||||
|
if h.App.Config.AlipayConfig.NotifyURL != "" { // 用于本地调试支付
|
||||||
|
notifyURL = h.App.Config.AlipayConfig.NotifyURL
|
||||||
|
} else {
|
||||||
|
notifyURL = fmt.Sprintf("%s/api/payment/notify/alipay", data.Host)
|
||||||
|
}
|
||||||
|
if h.App.Config.AlipayConfig.ReturnURL != "" { // 用于本地调试支付
|
||||||
|
returnURL = h.App.Config.AlipayConfig.ReturnURL
|
||||||
|
} else {
|
||||||
|
returnURL = fmt.Sprintf("%s/payReturn", data.Host)
|
||||||
|
}
|
||||||
money := fmt.Sprintf("%.2f", amount)
|
money := fmt.Sprintf("%.2f", amount)
|
||||||
payURL, err = h.alipayService.PayPC(payment.AlipayParams{
|
payURL, err = h.alipayService.PayPC(payment.AlipayParams{
|
||||||
OutTradeNo: orderNo,
|
OutTradeNo: orderNo,
|
||||||
Subject: product.Name,
|
Subject: product.Name,
|
||||||
TotalFee: money,
|
TotalFee: money,
|
||||||
ReturnURL: returnURL,
|
ReturnURL: returnURL,
|
||||||
NotifyURL: h.App.Config.AlipayConfig.NotifyURL,
|
NotifyURL: notifyURL,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.ERROR(c, "error with generate pay url: "+err.Error())
|
resp.ERROR(c, "error with generate pay url: "+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else if payWay == "hupi" { // 虎皮椒支付
|
break
|
||||||
returnURL := fmt.Sprintf("%s/payReturn", utils.GetBaseURL(h.App.Config.HuPiPayConfig.NotifyURL))
|
case "wechat":
|
||||||
|
if h.App.Config.WechatPayConfig.NotifyURL != "" {
|
||||||
|
notifyURL = h.App.Config.WechatPayConfig.NotifyURL
|
||||||
|
} else {
|
||||||
|
notifyURL = fmt.Sprintf("%s/api/payment/notify/wechat", data.Host)
|
||||||
|
}
|
||||||
|
payURL, err = h.wechatPayService.PayUrlNative(payment.WechatPayParams{
|
||||||
|
OutTradeNo: orderNo,
|
||||||
|
TotalFee: int(amount * 100),
|
||||||
|
Subject: product.Name,
|
||||||
|
NotifyURL: notifyURL,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
resp.ERROR(c, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "hupi":
|
||||||
|
if h.App.Config.HuPiPayConfig.NotifyURL != "" {
|
||||||
|
notifyURL = h.App.Config.HuPiPayConfig.NotifyURL
|
||||||
|
} else {
|
||||||
|
notifyURL = fmt.Sprintf("%s/api/payment/notify/hupi", data.Host)
|
||||||
|
}
|
||||||
|
if h.App.Config.HuPiPayConfig.ReturnURL != "" {
|
||||||
|
returnURL = h.App.Config.HuPiPayConfig.ReturnURL
|
||||||
|
} else {
|
||||||
|
returnURL = fmt.Sprintf("%s/payReturn", data.Host)
|
||||||
|
}
|
||||||
r, err := h.huPiPayService.Pay(payment.HuPiPayParams{
|
r, err := h.huPiPayService.Pay(payment.HuPiPayParams{
|
||||||
Version: "1.1",
|
Version: "1.1",
|
||||||
TradeOrderId: orderNo,
|
TradeOrderId: orderNo,
|
||||||
TotalFee: fmt.Sprintf("%f", amount),
|
TotalFee: fmt.Sprintf("%f", amount),
|
||||||
Title: product.Name,
|
Title: product.Name,
|
||||||
NotifyURL: h.App.Config.HuPiPayConfig.NotifyURL,
|
NotifyURL: notifyURL,
|
||||||
ReturnURL: returnURL,
|
ReturnURL: returnURL,
|
||||||
WapName: "GeekAI助手",
|
WapName: "GeekAI助手",
|
||||||
})
|
})
|
||||||
@ -129,23 +173,21 @@ func (h *PaymentHandler) Pay(c *gin.Context) {
|
|||||||
resp.ERROR(c, err.Error())
|
resp.ERROR(c, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
payURL = r.URL
|
payURL = r.URL
|
||||||
} else if payWay == "wechat" {
|
break
|
||||||
payURL, err = h.wechatPayService.PayUrlNative(payment.WechatPayParams{
|
case "geek":
|
||||||
OutTradeNo: orderNo,
|
if h.App.Config.GeekPayConfig.NotifyURL != "" {
|
||||||
TotalFee: int(amount * 100),
|
notifyURL = h.App.Config.GeekPayConfig.NotifyURL
|
||||||
Subject: product.Name,
|
} else {
|
||||||
NotifyURL: h.App.Config.WechatPayConfig.NotifyURL,
|
notifyURL = fmt.Sprintf("%s/api/payment/notify/geek", data.Host)
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
resp.ERROR(c, err.Error())
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
} else if payWay == "geek" {
|
if h.App.Config.GeekPayConfig.ReturnURL != "" {
|
||||||
returnURL := fmt.Sprintf("%s/payReturn", utils.GetBaseURL(h.App.Config.GeekPayConfig.NotifyURL))
|
data.Host = utils.GetBaseURL(h.App.Config.GeekPayConfig.ReturnURL)
|
||||||
if device == "wechat" {
|
}
|
||||||
returnURL = fmt.Sprintf("%s/mobile/profile", utils.GetBaseURL(h.App.Config.GeekPayConfig.NotifyURL))
|
if data.Device == "wechat" { // 微信客户端打开,调回手机端用户中心页面
|
||||||
|
returnURL = fmt.Sprintf("%s/mobile/profile", data.Host)
|
||||||
|
} else {
|
||||||
|
returnURL = fmt.Sprintf("%s/payReturn", data.Host)
|
||||||
}
|
}
|
||||||
params := payment.GeekPayParams{
|
params := payment.GeekPayParams{
|
||||||
OutTradeNo: orderNo,
|
OutTradeNo: orderNo,
|
||||||
@ -153,10 +195,10 @@ func (h *PaymentHandler) Pay(c *gin.Context) {
|
|||||||
Name: product.Name,
|
Name: product.Name,
|
||||||
Money: fmt.Sprintf("%f", amount),
|
Money: fmt.Sprintf("%f", amount),
|
||||||
ClientIP: c.ClientIP(),
|
ClientIP: c.ClientIP(),
|
||||||
Device: device,
|
Device: data.Device,
|
||||||
Type: payType,
|
Type: data.PayType,
|
||||||
ReturnURL: returnURL,
|
ReturnURL: returnURL,
|
||||||
NotifyURL: h.App.Config.GeekPayConfig.NotifyURL,
|
NotifyURL: notifyURL,
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := h.geekPayService.Pay(params)
|
res, err := h.geekPayService.Pay(params)
|
||||||
@ -165,6 +207,9 @@ func (h *PaymentHandler) Pay(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
payURL = res.PayURL
|
payURL = res.PayURL
|
||||||
|
default:
|
||||||
|
resp.ERROR(c, "不支持的支付渠道")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建订单
|
// 创建订单
|
||||||
@ -183,8 +228,8 @@ func (h *PaymentHandler) Pay(c *gin.Context) {
|
|||||||
Subject: product.Name,
|
Subject: product.Name,
|
||||||
Amount: amount,
|
Amount: amount,
|
||||||
Status: types.OrderNotPaid,
|
Status: types.OrderNotPaid,
|
||||||
PayWay: payWay,
|
PayWay: data.PayWay,
|
||||||
PayType: payType,
|
PayType: data.PayType,
|
||||||
Remark: utils.JsonEncode(remark),
|
Remark: utils.JsonEncode(remark),
|
||||||
}
|
}
|
||||||
err = h.DB.Create(&order).Error
|
err = h.DB.Create(&order).Error
|
||||||
|
@ -372,7 +372,7 @@ func main() {
|
|||||||
}),
|
}),
|
||||||
fx.Invoke(func(s *core.AppServer, h *handler.PaymentHandler) {
|
fx.Invoke(func(s *core.AppServer, h *handler.PaymentHandler) {
|
||||||
group := s.Engine.Group("/api/payment/")
|
group := s.Engine.Group("/api/payment/")
|
||||||
group.GET("doPay", h.Pay)
|
group.POST("doPay", h.Pay)
|
||||||
group.GET("payWays", h.GetPayWays)
|
group.GET("payWays", h.GetPayWays)
|
||||||
group.POST("notify/alipay", h.AlipayNotify)
|
group.POST("notify/alipay", h.AlipayNotify)
|
||||||
group.GET("notify/geek", h.GeekPayNotify)
|
group.GET("notify/geek", h.GeekPayNotify)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
VUE_APP_API_HOST=http://localhost:5678
|
VUE_APP_API_HOST=http://www.geekai.me:6004
|
||||||
VUE_APP_WS_HOST=ws://localhost:5678
|
VUE_APP_WS_HOST=ws://localhost:5678
|
||||||
VUE_APP_USER=18888888888
|
VUE_APP_USER=18888888888
|
||||||
VUE_APP_PASS=12345678
|
VUE_APP_PASS=12345678
|
||||||
|
@ -122,7 +122,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {onMounted, ref} from "vue"
|
import {onMounted, ref} from "vue"
|
||||||
import {ElMessage} from "element-plus";
|
import {ElMessage} from "element-plus";
|
||||||
import {httpGet} from "@/utils/http";
|
import {httpGet, httpPost} from "@/utils/http";
|
||||||
import {checkSession, getSystemInfo} from "@/store/cache";
|
import {checkSession, getSystemInfo} from "@/store/cache";
|
||||||
import UserProfile from "@/components/UserProfile.vue";
|
import UserProfile from "@/components/UserProfile.vue";
|
||||||
import PasswordDialog from "@/components/PasswordDialog.vue";
|
import PasswordDialog from "@/components/PasswordDialog.vue";
|
||||||
@ -200,11 +200,16 @@ const pay = (product, payWay) => {
|
|||||||
}
|
}
|
||||||
loading.value = true
|
loading.value = true
|
||||||
loadingText.value = "正在生成支付订单..."
|
loadingText.value = "正在生成支付订单..."
|
||||||
httpGet(`${process.env.VUE_APP_API_HOST}/api/payment/doPay`, {
|
let host = process.env.VUE_APP_API_HOST
|
||||||
|
if (host === '') {
|
||||||
|
host = `${location.protocol}://${location.host}`;
|
||||||
|
}
|
||||||
|
httpPost(`${process.env.VUE_APP_API_HOST}/api/payment/doPay`, {
|
||||||
product_id: product.id,
|
product_id: product.id,
|
||||||
pay_way: payWay.pay_way,
|
pay_way: payWay.pay_way,
|
||||||
pay_type: payWay.pay_type,
|
pay_type: payWay.pay_type,
|
||||||
user_id: user.value.id,
|
user_id: user.value.id,
|
||||||
|
host: host,
|
||||||
device: "jump"
|
device: "jump"
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
showDialog.value = true
|
showDialog.value = true
|
||||||
|
@ -296,11 +296,16 @@ const pay = (product,payWay) => {
|
|||||||
message: '正在创建订单',
|
message: '正在创建订单',
|
||||||
forbidClick: true,
|
forbidClick: true,
|
||||||
});
|
});
|
||||||
httpGet(`${process.env.VUE_APP_API_HOST}/api/payment/doPay`, {
|
let host = process.env.VUE_APP_API_HOST
|
||||||
|
if (host === '') {
|
||||||
|
host = `${location.protocol}://${location.host}`;
|
||||||
|
}
|
||||||
|
httpPost(`${process.env.VUE_APP_API_HOST}/api/payment/doPay`, {
|
||||||
product_id: product.id,
|
product_id: product.id,
|
||||||
pay_way: payWay.pay_way,
|
pay_way: payWay.pay_way,
|
||||||
pay_type: payWay.pay_type,
|
pay_type: payWay.pay_type,
|
||||||
user_id: userId.value,
|
user_id: userId.value,
|
||||||
|
host: host,
|
||||||
device: "wechat"
|
device: "wechat"
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
location.href = res.data
|
location.href = res.data
|
||||||
|
Loading…
Reference in New Issue
Block a user