支付调起+订单查询
This commit is contained in:
parent
0b844afa5f
commit
c1e354e4ab
|
@ -1,9 +1,10 @@
|
|||
package common
|
||||
|
||||
const (
|
||||
TOKEN_PRE = "player_token_"
|
||||
TOKEN_Admin = "Admin_token_"
|
||||
ADMIN_V1 = "/admin/pay/api/v1"
|
||||
TOKEN_PRE = "player_token_"
|
||||
TOKEN_Admin = "Admin_token_"
|
||||
ADMIN_V1 = "/admin/pay/api/v1"
|
||||
FRONT_API_V1 = "/v1"
|
||||
|
||||
// 支付渠道枚举,1微信JSAPI,2微信H5,3微信app,4微信Native,5微信小程序,6支付宝网页&移动应用,7支付宝小程序,8支付宝JSAPI
|
||||
PAY_CHANNEL_UNKNOWN = 0
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
package data
|
||||
|
||||
import "PaymentCenter/app/models/ordersmodel"
|
||||
|
||||
func GetOrderInfoById(id int64) (orderInfo ordersmodel.Orders, err error) {
|
||||
_, err = ordersmodel.GetInstance().GetDb().Where("Id = ?", id).Get(&orderInfo)
|
||||
if err != nil {
|
||||
return ordersmodel.Orders{}, err
|
||||
}
|
||||
return orderInfo, nil
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package front
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-pay/gopay/alipay"
|
||||
"github.com/go-pay/xlog"
|
||||
"github.com/qit-team/snow-core/log/logger"
|
||||
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// WxCallback 微信支付回调
|
||||
//func WxCallback(c *gin.Context) {
|
||||
// notifyReq, err := wechat.V3ParseNotify(c.Request)
|
||||
// if err != nil {
|
||||
// xlog.Error(err)
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// paymentService.WxPayCallBack(notifyReq)
|
||||
//
|
||||
// // ====↓↓↓====异步通知应答====↓↓↓====
|
||||
// // 退款通知http应答码为200且返回状态码为SUCCESS才会当做商户接收成功,否则会重试。
|
||||
// // 注意:重试过多会导致微信支付端积压过多通知而堵塞,影响其他正常通知。
|
||||
//
|
||||
// // 此写法是 gin 框架返回微信的写法
|
||||
// c.JSON(http.StatusOK, &wechat.V3NotifyRsp{Code: gopay.SUCCESS, Message: "成功"})
|
||||
//}
|
||||
|
||||
// AliCallback 支付宝支付回调
|
||||
func AliCallback(c *gin.Context) {
|
||||
notifyReq, err := alipay.ParseNotifyToBodyMap(c.Request) // c.Request 是 gin 框架的写法
|
||||
logger.Info(c, "AliCallback-回调数据", c.Request)
|
||||
if err != nil {
|
||||
xlog.Error(err)
|
||||
return
|
||||
}
|
||||
appId := notifyReq.Get("app_id")
|
||||
if appId == "" {
|
||||
c.String(http.StatusBadRequest, "%s", "fail")
|
||||
}
|
||||
|
||||
// todo 查询支付宝公钥证书信息,进行验证签名
|
||||
alipayPublicCert := ""
|
||||
ok, err := alipay.VerifySignWithCert([]byte(alipayPublicCert), notifyReq)
|
||||
if !ok {
|
||||
logger.Error(c, "AliCallback-回调数据,验签失败")
|
||||
c.String(http.StatusBadRequest, "%s", "fail")
|
||||
}
|
||||
|
||||
// todo 拼装数据触发下游回调,数据待定
|
||||
|
||||
c.String(http.StatusOK, "%s", "success")
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package front
|
||||
|
||||
type WxRequest struct {
|
||||
TradeNo string `json:"tradeNo" validate:"required"` // 交易流水号
|
||||
VoucherId string `json:"voucherId"` // 制码批次号
|
||||
VoucherCode string `json:"voucherCode"` // 串码
|
||||
CnclSt string `json:"cnclSt"` // 核销状态,4-已核销
|
||||
RedeemResult string `json:"redeemResult"` // 核销结果,00-成功,09- 失败
|
||||
MrchntNo string `json:"mrchntNo"` // 商户号
|
||||
Sign string `json:"sign"`
|
||||
}
|
||||
|
||||
type AliRequest struct {
|
||||
MerchantId int `form:"merchantId" validate:"required"`
|
||||
OutTradeNo string `form:"outTradeNo" validate:"required"`
|
||||
Status string `form:"status" validate:"required"`
|
||||
RechargeAccount string `form:"rechargeAccount"`
|
||||
CardCode string `form:"cardCode"`
|
||||
Sign string `form:"sign" validate:"required"`
|
||||
}
|
|
@ -1,7 +1,11 @@
|
|||
package requestmapping
|
||||
|
||||
import (
|
||||
"PaymentCenter/app/constants/common"
|
||||
"PaymentCenter/app/http/entities/front"
|
||||
)
|
||||
|
||||
var FrontRequestMap = map[string]func() interface{}{
|
||||
//"/v1/login": func() interface{} {
|
||||
// return new(front.LoginRequest)
|
||||
//},
|
||||
common.FRONT_API_V1 + "/notify/wx": func() interface{} { return new(front.WxRequest) },
|
||||
common.FRONT_API_V1 + "/notify/ali": func() interface{} { return new(front.AliRequest) },
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ package routes
|
|||
*/
|
||||
import (
|
||||
"PaymentCenter/app/http/controllers"
|
||||
"PaymentCenter/app/http/controllers/front"
|
||||
"PaymentCenter/app/http/middlewares"
|
||||
"PaymentCenter/app/http/trace"
|
||||
"PaymentCenter/app/utils/metric"
|
||||
|
@ -49,6 +50,16 @@ func RegisterRoute(router *gin.Engine) {
|
|||
//
|
||||
//}
|
||||
|
||||
v1 := router.Group("/v1", middlewares.ValidateRequest())
|
||||
{
|
||||
//回调处理
|
||||
notify := v1.Group("/notify")
|
||||
{
|
||||
notify.POST("/wx", front.WxCallback)
|
||||
notify.POST("/ali", front.AliCallback)
|
||||
}
|
||||
}
|
||||
|
||||
router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
|
||||
|
||||
//router.GET("/hello", controllers.HelloHandler)
|
||||
|
|
|
@ -14,7 +14,7 @@ func SingleTalk(tag uint64, ch interface{}, msg []byte) {
|
|||
// }
|
||||
// }
|
||||
// if !sendOk {
|
||||
// common.PikaTool.Zadd(utils.GetRealKey(common2.USER_MSG)+data.Msg.To, data, time.Now().Unix())
|
||||
// payCommon.PikaTool.Zadd(utils.GetRealKey(common2.USER_MSG)+data.Msg.To, data, time.Now().Unix())
|
||||
// }
|
||||
//}
|
||||
|
||||
|
|
|
@ -1,102 +0,0 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"PaymentCenter/app/constants/common"
|
||||
"PaymentCenter/app/constants/errorcode"
|
||||
"PaymentCenter/app/data"
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/go-pay/gopay"
|
||||
"github.com/go-pay/gopay/wechat/v3"
|
||||
"github.com/go-pay/xlog"
|
||||
"time"
|
||||
)
|
||||
|
||||
func ActivityGoodsCreateService(orderId int64) (err error) {
|
||||
// 获取订单信息
|
||||
orderInfo, err := data.GetOrderInfoById(orderId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if orderInfo.PayId == 0 {
|
||||
return errors.New("缺少订单信息,无法进行支付")
|
||||
}
|
||||
// 获取支付渠道
|
||||
payChannelInfo, err := data.GetPayChannelById(orderInfo.PayId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch payChannelInfo.ChannelType {
|
||||
case common.PAYCHANNEL_WX_H5:
|
||||
//todo 微信H5支付
|
||||
wxH5PayInfo()
|
||||
break
|
||||
case common.PAYCHANNEL_ALI_H5:
|
||||
//todo 支付宝H5支付
|
||||
aLiH5PayInfo()
|
||||
break
|
||||
default:
|
||||
return errors.New("暂不支持该支付渠道,请后续再使用")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func wxH5PayInfo(c context.Context) {
|
||||
// NewClientV3 初始化微信客户端 v3
|
||||
// mchid:商户ID 或者服务商模式的 sp_mchid
|
||||
// serialNo:商户证书的证书序列号
|
||||
// apiV3Key:apiV3Key,商户平台获取
|
||||
// privateKey:私钥 apiclient_key.pem 读取后的内容
|
||||
client, err := wechat.NewClientV3(MchId, SerialNo, APIv3Key, PrivateKey)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 设置微信平台API证书和序列号(推荐开启自动验签,无需手动设置证书公钥等信息)
|
||||
//client.SetPlatformCert([]byte(""), "")
|
||||
|
||||
// 启用自动同步返回验签,并定时更新微信平台API证书(开启自动验签时,无需单独设置微信平台API证书和序列号)
|
||||
err = client.AutoVerifySign()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 自定义配置http请求接收返回结果body大小,默认 10MB
|
||||
client.SetBodySize(10) // 没有特殊需求,可忽略此配置
|
||||
|
||||
// 打开Debug开关,输出日志,默认是关闭的
|
||||
client.DebugSwitch = gopay.DebugOn
|
||||
expire := time.Now().Add(10 * time.Minute).Format(time.RFC3339)
|
||||
// 初始化 BodyMap
|
||||
bm := make(gopay.BodyMap)
|
||||
bm.Set("sp_appid", "sp_appid").
|
||||
Set("sp_mchid", "sp_mchid").
|
||||
Set("sub_mchid", "sub_mchid").
|
||||
Set("description", "测试Jsapi支付商品").
|
||||
Set("out_trade_no", tradeNo).
|
||||
Set("time_expire", expire).
|
||||
Set("notify_url", "https://www.fmm.ink").
|
||||
SetBodyMap("amount", func(bm gopay.BodyMap) {
|
||||
bm.Set("total", 1).
|
||||
Set("currency", "CNY")
|
||||
}).
|
||||
SetBodyMap("payer", func(bm gopay.BodyMap) {
|
||||
bm.Set("sp_openid", "asdas")
|
||||
})
|
||||
|
||||
wxRsp, err := client.V3TransactionH5(c, bm)
|
||||
if err != nil {
|
||||
xlog.Error(err)
|
||||
return
|
||||
}
|
||||
if wxRsp.Code == errorcode.Success {
|
||||
xlog.Debugf("wxRsp: %#v", wxRsp.Response)
|
||||
return
|
||||
}
|
||||
xlog.Errorf("wxRsp:%s", wxRsp.Error)
|
||||
}
|
||||
|
||||
func aLiH5PayInfo() {
|
||||
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
package paymentService
|
||||
|
||||
import (
|
||||
"PaymentCenter/app/third/paymentService/payCommon"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/go-pay/gopay"
|
||||
"github.com/go-pay/gopay/alipay"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
aliClient *alipay.Client
|
||||
aliClientErr error
|
||||
aliOnce sync.Once
|
||||
)
|
||||
|
||||
// AliInitClient 使用提供的支付请求参数初始化支付宝客户端
|
||||
func AliInitClient(aliConfig AliPay) {
|
||||
aliOnce.Do(func() {
|
||||
// 初始化支付宝客户端
|
||||
// appid:应用ID
|
||||
// privateKey:应用私钥,支持PKCS1和PKCS8
|
||||
// isProd:是否是正式环境,沙箱环境请选择新版沙箱应用。
|
||||
aliClient, aliClientErr = alipay.NewClient(aliConfig.AppId, aliConfig.PrivateKey, true)
|
||||
})
|
||||
// 自定义配置http请求接收返回结果body大小,默认 10MB
|
||||
aliClient.SetBodySize(10) // 没有特殊需求,可忽略此配置
|
||||
|
||||
// 打开Debug开关,输出日志,默认关闭
|
||||
aliClient.DebugSwitch = gopay.DebugOn
|
||||
|
||||
// 设置支付宝请求 公共参数
|
||||
// 注意:具体设置哪些参数,根据不同的方法而不同,此处列举出所有设置参数
|
||||
aliClient.SetLocation(alipay.LocationShanghai). // 设置时区,不设置或出错均为默认服务器时间
|
||||
SetCharset(alipay.UTF8). // 设置字符编码,不设置默认 utf-8
|
||||
SetSignType(alipay.RSA2) // 设置签名类型,不设置默认 RSA2
|
||||
|
||||
// 自动同步验签(只支持证书模式)
|
||||
// 传入 alipayPublicCert.crt 内容
|
||||
aliClient.AutoVerifySign(aliConfig.AlipayPublicCert)
|
||||
|
||||
// 证书内容
|
||||
aliClientErr = aliClient.SetCertSnByContent(aliConfig.AppPublicCert, aliConfig.AlipayRootCert, aliConfig.AlipayPublicCert)
|
||||
}
|
||||
|
||||
// GetAliClient 获取已经初始化的支付宝客户端
|
||||
func GetAliClient() (*alipay.Client, error) {
|
||||
if aliClient == nil {
|
||||
return nil, errors.New("client not initialized")
|
||||
}
|
||||
if aliClientErr != nil {
|
||||
return nil, aliClientErr
|
||||
}
|
||||
return aliClient, nil
|
||||
}
|
||||
|
||||
// ALiH5PayInfo 支付宝手机网站支付
|
||||
func ALiH5PayInfo(c context.Context, payOrderRequest PayOrderRequest) (string, error) {
|
||||
// 初始化支付宝客户端
|
||||
AliInitClient(payOrderRequest.Ali)
|
||||
|
||||
// 获取支付宝客户端
|
||||
aliClient, err := GetAliClient()
|
||||
if err != nil {
|
||||
fmt.Println("Failed to get client:", err)
|
||||
return "", err
|
||||
}
|
||||
// 初始化 BodyMap
|
||||
amount := float64(payOrderRequest.Amount) / 100.0
|
||||
|
||||
bm := make(gopay.BodyMap)
|
||||
bm.Set("out_trade_no", payOrderRequest.OrderId).
|
||||
Set("total_amount", amount).
|
||||
Set("subject", payOrderRequest.Description).
|
||||
Set("notify_url", payCommon.ALI_NOTIFY_URL)
|
||||
|
||||
aliRsp, err := aliClient.TradeWapPay(c, bm)
|
||||
if err != nil {
|
||||
if bizErr, ok := alipay.IsBizError(err); ok {
|
||||
return "", bizErr
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
return aliRsp, nil
|
||||
}
|
||||
|
||||
// ALiOrderQuery 查询支付宝订单
|
||||
func ALiOrderQuery(ctx context.Context, aliConfig AliPay, OrderNo string) (PayOrderQueryInfo, error) {
|
||||
// 初始化支付宝客户端
|
||||
AliInitClient(aliConfig)
|
||||
|
||||
// 获取支付宝客户端
|
||||
aliClient, err := GetAliClient()
|
||||
if err != nil {
|
||||
fmt.Println("Failed to get client:", err)
|
||||
return PayOrderQueryInfo{}, err
|
||||
}
|
||||
// 请求参数
|
||||
bm := make(gopay.BodyMap)
|
||||
bm.Set("out_trade_no", OrderNo)
|
||||
|
||||
// 查询订单
|
||||
aliRsp, err := aliClient.TradeQuery(ctx, bm)
|
||||
if err != nil {
|
||||
if bizErr, ok := alipay.IsBizError(err); ok {
|
||||
return PayOrderQueryInfo{}, bizErr
|
||||
}
|
||||
return PayOrderQueryInfo{}, err
|
||||
}
|
||||
// 同步返回验签
|
||||
ok, err := alipay.VerifySyncSignWithCert(aliConfig.AlipayPublicCert, aliRsp.SignData, aliRsp.Sign)
|
||||
if err != nil || !ok {
|
||||
return PayOrderQueryInfo{}, errors.New(fmt.Sprintf("验签失败,失败原因:%s", err.Error()))
|
||||
}
|
||||
|
||||
// 映射交易状态
|
||||
tradeState := ""
|
||||
tradeStateDesc := ""
|
||||
switch aliRsp.Response.TradeStatus {
|
||||
case "TRADE_SUCCESS":
|
||||
tradeState = "SUCCESS"
|
||||
tradeStateDesc = "交易支付成功"
|
||||
case "REFUND":
|
||||
tradeState = "REFUND"
|
||||
case "WAIT_BUYER_PAY":
|
||||
tradeState = "NOTPAY"
|
||||
tradeStateDesc = "交易创建,等待买家付款"
|
||||
case "TRADE_CLOSED":
|
||||
tradeState = "CLOSED"
|
||||
tradeStateDesc = "未付款交易超时关闭,或支付完成后全额退款"
|
||||
}
|
||||
|
||||
amountTotal, _ := strconv.Atoi(aliRsp.Response.TotalAmount)
|
||||
payerTotal, _ := strconv.Atoi(aliRsp.Response.BuyerPayAmount)
|
||||
// 构建数据
|
||||
return PayOrderQueryInfo{
|
||||
AppId: aliConfig.AppId,
|
||||
OutTradeNo: aliRsp.Response.OutTradeNo,
|
||||
TransactionId: aliRsp.Response.TradeNo,
|
||||
TradeState: tradeState,
|
||||
TradeStateDesc: tradeStateDesc,
|
||||
SuccessTime: aliRsp.Response.SendPayDate,
|
||||
AmountTotal: int64(amountTotal * 100),
|
||||
PayerTotal: int64(payerTotal * 100),
|
||||
}, nil
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package payCommon
|
||||
|
||||
const (
|
||||
// 支付渠道枚举,1微信JSAPI,2微信H5,3微信app,4微信Native,5微信小程序,6支付宝网页&移动应用,7支付宝小程序,8支付宝JSAPI
|
||||
PAY_CHANNEL_UNKNOWN = 0
|
||||
PAY_CHANNEL_WECHAT_JSAPI = 1
|
||||
PAY_CHANNEL_WECHAT_H5 = 2
|
||||
PAY_CHANNEL_WECHAT_APP = 3
|
||||
PAY_CHANNEL_WECHAT_NATIVE = 4
|
||||
PAY_CHANNEL_WECHAT_MINI = 5
|
||||
PAY_CHANNEL_ALIPAY_WEB = 6
|
||||
PAY_CHANNEL_ALIPAY_MINI = 7
|
||||
PAY_CHANNEL_ALIPAY_JSAPI = 8
|
||||
|
||||
PAY_SUCCESS_CODE = 200 // 支付响应成功
|
||||
PAY_ERROR_CODE = 500 // 支付响应失败
|
||||
PAY_NOT_FOUND_CODE = 404 // 未找到支付渠道
|
||||
|
||||
WX_SUCCESS_CODE = 200 // 微信状态码返回成功
|
||||
WX_NOTIFY_URL = "" // 微信支付回调地址
|
||||
|
||||
ALI_NOTIFY_URL = "" // 支付宝支付回调地址
|
||||
|
||||
ORDER_NO_TYPE_ORDER_NO = 2
|
||||
|
||||
PAY_CHANNLE_TYPE_WECHAT = 1 // 支付类型: 微信
|
||||
PAY_CHANNLE_TYPE_ZFB = 2 // 支付类型:支付宝
|
||||
)
|
|
@ -0,0 +1,130 @@
|
|||
package paymentService
|
||||
|
||||
import (
|
||||
"PaymentCenter/app/third/paymentService/payCommon"
|
||||
"context"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type PayOrderRequest struct {
|
||||
OrderId int64 `json:"order_id"` // 平台订单号
|
||||
ChannelType int `json:"channel_type"` // 支付方式
|
||||
Description string `json:"description"` // 商品描述
|
||||
Amount int `json:"amount"` // 金额单位为分
|
||||
PayerClientIp string `json:"payer_client_ip"` // 终端IP
|
||||
Wx WxPay `json:"wx"`
|
||||
Ali AliPay `json:"ali"`
|
||||
}
|
||||
|
||||
type WxPay struct {
|
||||
AppId string `json:"app_id"` // 应用ID
|
||||
MchId string `json:"mch_id"` // 商户ID 或者服务商模式的 sp_mchid
|
||||
SerialNo string `json:"serial_no"` // 商户证书的证书序列号
|
||||
ApiV3Key string `json:"api_v_3_key"` // apiV3Key,商户平台获取
|
||||
PrivateKey string `json:"private_key"` // 私钥 apiclient_key.pem 读取后的内容
|
||||
}
|
||||
|
||||
type AliPay struct {
|
||||
AppId string `json:"app_id"` // 应用ID
|
||||
PrivateKey string `json:"private_key"` // 应用私钥
|
||||
AppPublicCert []byte `json:"app_public_cert"` // 应用公钥
|
||||
AlipayRootCert []byte `json:"alipay_root_cert"` // 支付宝根证书
|
||||
AlipayPublicCert []byte `json:"alipay_public_cert"` // 支付宝公钥
|
||||
}
|
||||
|
||||
type PayOrderResponse struct {
|
||||
Code int `json:"code"`
|
||||
ErrorMsg string `json:"error_msg"`
|
||||
Result string `json:"result"`
|
||||
}
|
||||
|
||||
// PaymentService 统一发起支付
|
||||
func PaymentService(c context.Context, payOrderRequest PayOrderRequest) (payOrderResponse PayOrderResponse) {
|
||||
switch payOrderRequest.ChannelType {
|
||||
case payCommon.PAY_CHANNEL_WECHAT_H5:
|
||||
// 微信H5支付
|
||||
info, err := WxH5PayInfo(c, payOrderRequest)
|
||||
if err != nil {
|
||||
return PayOrderResponse{
|
||||
Code: payCommon.PAY_ERROR_CODE,
|
||||
ErrorMsg: err.Error(),
|
||||
}
|
||||
}
|
||||
return PayOrderResponse{
|
||||
Code: payCommon.PAY_SUCCESS_CODE,
|
||||
ErrorMsg: "",
|
||||
Result: info,
|
||||
}
|
||||
case payCommon.PAY_CHANNEL_ALIPAY_WEB:
|
||||
// 支付宝H5支付
|
||||
info, err := ALiH5PayInfo(c, payOrderRequest)
|
||||
if err != nil {
|
||||
return PayOrderResponse{
|
||||
Code: payCommon.PAY_ERROR_CODE,
|
||||
ErrorMsg: err.Error(),
|
||||
}
|
||||
}
|
||||
return PayOrderResponse{
|
||||
Code: payCommon.PAY_SUCCESS_CODE,
|
||||
ErrorMsg: "",
|
||||
Result: info,
|
||||
}
|
||||
default:
|
||||
return PayOrderResponse{
|
||||
Code: payCommon.PAY_NOT_FOUND_CODE,
|
||||
ErrorMsg: "暂不支持该支付渠道,请后续再使用",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type PayOrderQueryRequest struct {
|
||||
OrderId int64 `json:"order_id"` // 商户订单号
|
||||
PayChannel int `json:"pay_channel"` // 支付渠道类型 1:wx,2:zfb
|
||||
Wx WxPay `json:"wx"`
|
||||
Ali AliPay `json:"ali"`
|
||||
}
|
||||
|
||||
type PayOrderQueryResponse struct {
|
||||
Code int `json:"code"`
|
||||
ErrorMsg string `json:"error_msg"`
|
||||
Result PayOrderQueryInfo `json:"result"`
|
||||
}
|
||||
|
||||
type PayOrderQueryInfo struct {
|
||||
AppId string `json:"app_id"` // 应用ID
|
||||
OutTradeNo string `json:"out_trade_no"` // 商家订单号
|
||||
TransactionId string `json:"transaction_id"` // 第三方订单号
|
||||
TradeState string `json:"trade_state"` // 交易状态 SUCCESS:成功、REFUND:转入退款、NOTPAY:未支付、CLOSED:已关闭
|
||||
TradeStateDesc string `json:"trade_state_desc"` // 交易描述
|
||||
SuccessTime string `json:"success_time"` // 交易完成时间
|
||||
AmountTotal int64 `json:"amount_total"` // 订单总金额,单位:分
|
||||
PayerTotal int64 `json:"payer_total"` // 支付总金额,单位:分
|
||||
}
|
||||
|
||||
// PayOrderQuery 查询订单状态
|
||||
func PayOrderQuery(c context.Context, payOrderQueryRequest PayOrderQueryRequest) PayOrderQueryResponse {
|
||||
var err error
|
||||
var info PayOrderQueryInfo
|
||||
switch payOrderQueryRequest.PayChannel {
|
||||
case payCommon.PAY_CHANNLE_TYPE_WECHAT:
|
||||
// 微信H5支付
|
||||
info, err = WxOrderQuery(c, payOrderQueryRequest.Wx, strconv.FormatInt(payOrderQueryRequest.OrderId, 10))
|
||||
case payCommon.PAY_CHANNLE_TYPE_ZFB:
|
||||
info, err = ALiOrderQuery(c, payOrderQueryRequest.Ali, strconv.FormatInt(payOrderQueryRequest.OrderId, 10))
|
||||
default:
|
||||
return PayOrderQueryResponse{
|
||||
Code: payCommon.PAY_ERROR_CODE,
|
||||
ErrorMsg: "暂不支持该支付渠道,请后续再使用",
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return PayOrderQueryResponse{
|
||||
Code: payCommon.PAY_ERROR_CODE,
|
||||
ErrorMsg: err.Error(),
|
||||
}
|
||||
}
|
||||
return PayOrderQueryResponse{
|
||||
Code: payCommon.PAY_SUCCESS_CODE,
|
||||
Result: info,
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,169 @@
|
|||
package paymentService
|
||||
|
||||
import (
|
||||
"PaymentCenter/app/third/paymentService/payCommon"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/go-pay/gopay"
|
||||
"github.com/go-pay/gopay/wechat/v3"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
wxClient *wechat.ClientV3
|
||||
clientErr error
|
||||
once sync.Once
|
||||
)
|
||||
|
||||
// InitClient 使用提供的支付请求参数初始化微信客户端
|
||||
func InitClient(wxConfig WxPay) {
|
||||
once.Do(func() {
|
||||
// NewClientV3 初始化微信客户端 v3
|
||||
// mchid:商户ID 或者服务商模式的 sp_mchid
|
||||
// serialNo:商户证书的证书序列号
|
||||
// apiV3Key:apiV3Key,商户平台获取
|
||||
// privateKey:私钥 apiclient_key.pem 读取后的内容
|
||||
wxClient, clientErr = wechat.NewClientV3(
|
||||
wxConfig.MchId,
|
||||
wxConfig.SerialNo,
|
||||
wxConfig.ApiV3Key,
|
||||
wxConfig.PrivateKey,
|
||||
)
|
||||
})
|
||||
// 启用自动同步返回验签,并定时更新微信平台API证书(开启自动验签时,无需单独设置微信平台API证书和序列号)
|
||||
clientErr = wxClient.AutoVerifySign()
|
||||
|
||||
// 自定义配置http请求接收返回结果body大小,默认 10MB
|
||||
wxClient.SetBodySize(10) // 没有特殊需求,可忽略此配置
|
||||
|
||||
// 打开Debug开关,输出日志,默认是关闭的
|
||||
wxClient.DebugSwitch = gopay.DebugOn
|
||||
}
|
||||
|
||||
// GetClient 获取已经初始化的微信客户端
|
||||
func GetClient() (*wechat.ClientV3, error) {
|
||||
if wxClient == nil {
|
||||
return nil, errors.New("client not initialized")
|
||||
}
|
||||
if clientErr != nil {
|
||||
return nil, clientErr
|
||||
}
|
||||
return wxClient, nil
|
||||
}
|
||||
|
||||
// WxH5PayInfo 微信H5支付
|
||||
func WxH5PayInfo(c context.Context, payOrderRequest PayOrderRequest) (string, error) {
|
||||
// 初始化微信客户端
|
||||
InitClient(payOrderRequest.Wx)
|
||||
|
||||
// 获取微信客户端
|
||||
wxClient, err := GetClient()
|
||||
if err != nil {
|
||||
fmt.Println("Failed to get client:", err)
|
||||
return "", err
|
||||
}
|
||||
expire := time.Now().Add(10 * time.Minute).Format(time.RFC3339)
|
||||
// 初始化 BodyMap
|
||||
bm := make(gopay.BodyMap)
|
||||
bm.Set("appid", payOrderRequest.Wx.AppId).
|
||||
Set("mchid", payOrderRequest.Wx.MchId).
|
||||
Set("description", payOrderRequest.Description).
|
||||
Set("out_trade_no", payOrderRequest.OrderId).
|
||||
Set("time_expire", expire).
|
||||
Set("notify_url", payCommon.WX_NOTIFY_URL).
|
||||
SetBodyMap("amount", func(bm gopay.BodyMap) {
|
||||
bm.Set("total", payOrderRequest.Amount).
|
||||
Set("currency", "CNY")
|
||||
}).
|
||||
SetBodyMap("scene_info", func(bm gopay.BodyMap) {
|
||||
bm.Set("payer_client_ip", payOrderRequest.PayerClientIp).
|
||||
SetBodyMap("h5_info", func(bm gopay.BodyMap) {
|
||||
bm.Set("type", "common")
|
||||
})
|
||||
})
|
||||
|
||||
wxRsp, err := wxClient.V3TransactionH5(c, bm)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if wxRsp.Code != wechat.Success || wxRsp.Response.H5Url == "" {
|
||||
return "", errors.New(fmt.Sprintf("发起支付失败,失败状态码:%d, 失败原因:%s", wxRsp.Code, wxRsp.Error))
|
||||
}
|
||||
return wxRsp.Response.H5Url, nil
|
||||
}
|
||||
|
||||
//func WxPayCallBack(notifyReq *wechat.V3NotifyReq) error {
|
||||
// // 获取附加数据中的信息
|
||||
// appId := notifyReq.Resource.AssociatedData
|
||||
//
|
||||
// payOrderRequest := PayOrderRequest{}
|
||||
// // 初始化微信客户端
|
||||
// InitClient(payOrderRequest)
|
||||
//
|
||||
// // 获取微信客户端
|
||||
// wxClient, err := GetClient()
|
||||
// if err != nil {
|
||||
// fmt.Println("Failed to get client:", err)
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// // 获取微信平台证书
|
||||
// certMap := wxClient.WxPublicKeyMap()
|
||||
// // 验证异步通知的签名
|
||||
// err = notifyReq.VerifySignByPKMap(certMap)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// objPtr := ""
|
||||
// // 通用通知解密(推荐此方法)
|
||||
// result := notifyReq.DecryptCipherTextToStruct(apiV3Key, objPtr)
|
||||
//}
|
||||
|
||||
// WxOrderQuery 查询微信订单
|
||||
func WxOrderQuery(ctx context.Context, wxConfig WxPay, orderNo string) (PayOrderQueryInfo, error) {
|
||||
// 初始化微信客户端
|
||||
InitClient(wxConfig)
|
||||
|
||||
// 获取微信客户端
|
||||
wxClient, err := GetClient()
|
||||
if err != nil {
|
||||
fmt.Println("Failed to get client:", err)
|
||||
return PayOrderQueryInfo{}, err
|
||||
}
|
||||
|
||||
wxRsp, err := wxClient.V3TransactionQueryOrder(ctx, payCommon.ORDER_NO_TYPE_ORDER_NO, orderNo)
|
||||
if err != nil {
|
||||
return PayOrderQueryInfo{}, err
|
||||
}
|
||||
if wxRsp.Code != wechat.Success {
|
||||
return PayOrderQueryInfo{}, errors.New(fmt.Sprintf("查询订单接口错误,错误状态码:%d, 错误信息:%s", wxRsp.Code, wxRsp.Error))
|
||||
}
|
||||
|
||||
// 映射交易状态
|
||||
tradeState := ""
|
||||
switch wxRsp.Response.TradeState {
|
||||
case "SUCCESS":
|
||||
tradeState = "SUCCESS"
|
||||
case "REFUND":
|
||||
tradeState = "REFUND"
|
||||
case "NOTPAY":
|
||||
tradeState = "NOTPAY"
|
||||
case "CLOSED":
|
||||
tradeState = "CLOSED"
|
||||
}
|
||||
amountTotal := wxRsp.Response.Amount.Total
|
||||
payerTotal := wxRsp.Response.Amount.PayerTotal
|
||||
|
||||
return PayOrderQueryInfo{
|
||||
AppId: wxRsp.Response.Appid,
|
||||
OutTradeNo: wxRsp.Response.OutTradeNo,
|
||||
TransactionId: wxRsp.Response.TransactionId,
|
||||
TradeState: tradeState,
|
||||
TradeStateDesc: wxRsp.Response.TradeStateDesc,
|
||||
SuccessTime: wxRsp.Response.SuccessTime,
|
||||
AmountTotal: int64(amountTotal),
|
||||
PayerTotal: int64(payerTotal),
|
||||
}, nil
|
||||
}
|
|
@ -23,8 +23,8 @@ type CMqManager struct {
|
|||
|
||||
func (this *CMqManager) InitMq() {
|
||||
this.mqs = make(map[string]Imq)
|
||||
//this.mqs[common.MQ_RABBIT] = RabbitMq{}
|
||||
//this.mqs[common.MQ_NSQ] = NsqMq{}
|
||||
//this.mqs[payCommon.MQ_RABBIT] = RabbitMq{}
|
||||
//this.mqs[payCommon.MQ_NSQ] = NsqMq{}
|
||||
this.mqs[common3.MQ_NATS] = mq.NatsMq{}
|
||||
this.mqs[common3.MQ_KFK] = mq.KafkaMq{}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
|
||||
/**
|
||||
*事件触发
|
||||
event.EventManger.TrigerEvent(common.Event_USER_LOG_IN, param)
|
||||
event.EventManger.TrigerEvent(payCommon.Event_USER_LOG_IN, param)
|
||||
*/
|
||||
|
||||
var EventManger *EventManagerFactory
|
||||
|
|
Loading…
Reference in New Issue