支付调起+订单查询
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