PaymentCenter/app/third/paymentService/psbc_service.go

222 lines
6.6 KiB
Go

package paymentService
import (
"PaymentCenter/app/third/paymentService/payCommon"
psbc "PaymentCenter/app/third/paymentService/psbc"
"PaymentCenter/config"
"context"
"errors"
"fmt"
"github.com/qit-team/snow-core/log/logger"
"strconv"
)
type PsbcPay struct {
MerchantId string `json:"merchant_id"` // 商户ID
MchtNo string `json:"mcht_no"` // 商户号
AppID string `json:"app_id"` // 应用ID
SopPublicKey string `json:"sop_public_key"` // SOP公钥
PrivateKey string `json:"private_key"` // 商户私钥
Pubkey string `json:"pubkey"` // 商户公钥
BankKey string `json:"bank_key"` // 银行公钥
Sha string `json:"sha"` // SHA密钥
ReturnUrl string `json:"return_url"` // 支付返回地址
SuccessUrl string `json:"success_url"` // 支付成功地址
NotifyUrl string `json:"notify_url"` // 回调通知地址
ShowTitleBar string `json:"show_title_bar"` // 是否显示标题栏
LoginHost string `json:"login_host"` // 登录服务地址
OrderHost string `json:"order_host"` // 订单服务地址
FileHost string `json:"file_host"` // 文件服务地址
ShopId string `json:"shop_id"` // 店铺ID
}
func PsbcInitClient(psbcConfig PsbcPay) *psbc.Client {
cfg := psbc.Config{
MerchantId: psbcConfig.MerchantId,
MchtNo: psbcConfig.MchtNo,
AppID: psbcConfig.AppID,
SopPublicKey: psbcConfig.SopPublicKey,
PrivateKey: psbcConfig.PrivateKey,
Pubkey: psbcConfig.Pubkey,
BankKey: psbcConfig.BankKey,
Sha: psbcConfig.Sha,
ReturnUrl: psbcConfig.ReturnUrl,
SuccessUrl: psbcConfig.SuccessUrl,
NotifyUrl: psbcConfig.NotifyUrl,
ShowTitleBar: psbcConfig.ShowTitleBar,
LoginHost: psbcConfig.LoginHost,
OrderHost: psbcConfig.OrderHost,
FileHost: psbcConfig.FileHost,
ShopId: psbcConfig.ShopId,
}
return psbc.NewClient(cfg)
}
func PsbcPayInfo(c context.Context, payOrderRequest PayOrderRequest) (string, error) {
envConfig := config.GetConf()
notifyUrl := fmt.Sprintf(envConfig.PayService.Host+payCommon.PSBC_NOTIFY_URL_TEST+"%d", payOrderRequest.PayChannelId)
psbcConfig := payOrderRequest.Psbc
psbcConfig.NotifyUrl = notifyUrl
psbcClient := PsbcInitClient(psbcConfig)
amount := fmt.Sprintf("%.2f", float64(payOrderRequest.Amount)/100.0)
orderNo := strconv.FormatInt(payOrderRequest.OrderId, 10)
req := psbc.PaymentLinkRequest{
OrderNo: orderNo,
ProductName: payOrderRequest.Description,
Price: amount,
BackUrl: payOrderRequest.ReturnUrl,
}
resp, err := psbcClient.CreatePaymentLink(req)
if err != nil {
logger.Error(c, "PsbcPayInfo 发生错误", fmt.Sprintf("错误信息:%s", err.Error()))
return "", err
}
return resp.PayUrl, nil
}
func PsbcOrderQuery(ctx context.Context, psbcConfig PsbcPay, orderNo string) (PayOrderQueryInfo, error) {
psbcClient := PsbcInitClient(psbcConfig)
resp, err := psbcClient.OrderQuery(orderNo)
if err != nil {
logger.Error(ctx, "PsbcOrderQuery 发生错误", fmt.Sprintf("错误信息:%s", err.Error()))
return PayOrderQueryInfo{}, err
}
tradeState := "NOTPAY"
tradeStateDesc := ""
switch resp.OrderSta {
case "03":
tradeState = "SUCCESS"
tradeStateDesc = "支付成功"
case "04", "05":
tradeState = "FAIL"
tradeStateDesc = "支付失败"
default:
tradeState = "NOTPAY"
tradeStateDesc = "未支付"
}
amountTotal := int64(0)
payerTotal := int64(0)
outTradeNo, _ := strconv.ParseInt(orderNo, 10, 64)
return PayOrderQueryInfo{
AppId: psbcConfig.AppID,
OutTradeNo: outTradeNo,
TransactionId: "",
TradeState: tradeState,
TradeStateDesc: tradeStateDesc,
SuccessTime: "",
AmountTotal: amountTotal,
PayerTotal: payerTotal,
}, nil
}
func PsbcRefundOrder(ctx context.Context, orderRefundRequest OrderRefundRequest) (OrderRefundInfo, error) {
psbcClient := PsbcInitClient(orderRefundRequest.Psbc)
refundAmount := fmt.Sprintf("%.2f", float64(orderRefundRequest.RefundAmount)/100.0)
orderNo := strconv.FormatInt(orderRefundRequest.OrderId, 10)
req := psbc.RefundRequest{
OrderNo: orderNo,
Price: refundAmount,
OrgTxnSeq: orderRefundRequest.TransactionId,
RefundDesc: orderRefundRequest.RefundReason,
}
resp, err := psbcClient.Refund(req)
if err != nil {
logger.Error(ctx, "PsbcRefundOrder 发生错误", fmt.Sprintf("申请退款接口失败,错误信息:%s", err.Error()))
return OrderRefundInfo{}, err
}
refundStatus := payCommon.PAY_REFUND_STATU_COMMON
switch resp.RefundOrderSta {
case "03":
refundStatus = payCommon.PAY_REFUND_STATU_SUCCESS
case "04":
refundStatus = payCommon.PAY_REFUND_STATU_FAIL
}
refundFee := int64(0)
if resp.TxnAmt != "" {
amountFloat, err := strconv.ParseFloat(resp.TxnAmt, 64)
if err == nil {
refundFee = int64(amountFloat * 100)
}
}
return OrderRefundInfo{
OutTradeNo: orderRefundRequest.OrderId,
TransactionId: resp.RefundOrderNo,
RefundFee: refundFee,
RefundOrderId: orderRefundRequest.RefundOrderId,
RefundStatus: refundStatus,
RefundSuccessTime: "",
}, nil
}
func PsbcCloseOrder(ctx context.Context, orderCloseRequest OrderCloseRequest) (OrderCloseInfo, error) {
return OrderCloseInfo{
OutTradeNo: orderCloseRequest.OrderId,
}, nil
}
func PsbcVerifyAndParseNotify(rawBody string, psbcConfig PsbcPay) (orderId int64, amountTotal int64, payerTotal int64, status string, err error) {
psbcClient := PsbcInitClient(psbcConfig)
result, err := psbcClient.VerifyAndParseNotify(rawBody)
if err != nil {
logger.Error(context.Background(), "PsbcVerifyAndParseNotify 发生错误", fmt.Sprintf("验签解密失败,错误信息:%s", err.Error()))
return 0, 0, 0, "", err
}
orderNoStr := ""
if orderNo, ok := result["orderNo"].(string); ok {
orderNoStr = orderNo
}
if orderNoStr == "" {
return 0, 0, 0, "", errors.New("回调数据中缺少订单号")
}
orderId, err = strconv.ParseInt(orderNoStr, 10, 64)
if err != nil {
logger.Error(context.Background(), "PsbcVerifyAndParseNotify 发生错误", fmt.Sprintf("订单号转换失败,错误信息:%s", err.Error()))
return 0, 0, 0, "", err
}
amountStr := ""
if amount, ok := result["amount"].(string); ok {
amountStr = amount
}
if amountStr != "" {
amountFloat, err := strconv.ParseFloat(amountStr, 64)
if err == nil {
amountTotal = int64(amountFloat * 100)
payerTotal = amountTotal
}
}
orderSta := ""
if sta, ok := result["orderSta"].(string); ok {
orderSta = sta
}
switch orderSta {
case "03":
status = "SUCCESS"
case "04", "05":
status = "FAIL"
default:
status = "NOTPAY"
}
return orderId, amountTotal, payerTotal, status, nil
}