PaymentCenter/app/third/paymentService/psbc_service.go

201 lines
6.7 KiB
Go

package paymentService
import (
"PaymentCenter/app/third/paymentService/payCommon"
psbc "PaymentCenter/app/third/paymentService/psbc"
"PaymentCenter/config"
"context"
"encoding/json"
"fmt"
"github.com/qit-team/snow-core/log/logger"
"strconv"
"time"
)
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"` // 商户私钥
PrivateKeyCallback string `json:"private_key_callback"` // 邮储响应解密的私钥
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"` // 回调通知地址
LoginHost string `json:"login_host"` // 登录服务地址
OrderHost string `json:"order_host"` // 订单服务地址
FileHost string `json:"file_host"` // 文件服务地址
ShopId string `json:"shop_id"` // 店铺ID
Psbcmcc string `json:"psbcmcc"` // 三方服务商标识
PayUrl string `json:"pay_url"` // 支付地址
}
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,
LoginHost: psbcConfig.LoginHost,
OrderHost: psbcConfig.OrderHost,
FileHost: psbcConfig.FileHost,
ShopId: psbcConfig.ShopId,
Psbcmcc: psbcConfig.Psbcmcc,
PrivateKeyCallback: psbcConfig.PrivateKeyCallback,
PayUrl: psbcConfig.PayUrl,
}
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.CreatePaymentLinkWithBackUrl(req)
if err != nil {
logger.Error(c, "PsbcPayInfo 发生错误", fmt.Sprintf("错误信息:%s", err.Error()))
return "", err
}
respBytes, err := json.Marshal(resp)
if err != nil {
logger.Error(c, "PsbcPayInfo 序列化失败", fmt.Sprintf("错误信息:%s", err.Error()))
return "", err
}
return string(respBytes), 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 = "未支付"
}
var amountTotal int64
var payerTotal int64
if resp.TxnAmt != "" {
amountFloat, err := strconv.ParseFloat(resp.TxnAmt, 64)
if err == nil {
amountTotal = int64(amountFloat * 100)
payerTotal = int64(amountFloat * 100)
}
}
successTime := ""
outTradeNo, _ := strconv.ParseInt(orderNo, 10, 64)
return PayOrderQueryInfo{
AppId: psbcConfig.AppID,
OutTradeNo: outTradeNo,
TransactionId: resp.OrderNo,
TradeState: tradeState,
TradeStateDesc: tradeStateDesc,
SuccessTime: 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
if resp.RespCode == "000000" && resp.RefundOrderSta == "03" {
refundStatus = payCommon.PAY_REFUND_STATU_SUCCESS
} else {
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: time.Now().Format(time.DateTime),
}, nil
}
func PsbcCloseOrder(ctx context.Context, orderCloseRequest OrderCloseRequest) (OrderCloseInfo, error) {
return OrderCloseInfo{
OutTradeNo: orderCloseRequest.OrderId,
}, nil
}
func PsbcVerifyAndParseNotify(rawBody string, psbcConfig PsbcPay) (result *psbc.YouChuOrderNotifyRequest, err error) {
psbcClient := PsbcInitClient(psbcConfig)
result, err = psbcClient.VerifyAndParseNotify(rawBody)
if err != nil {
logger.Error(context.Background(), "PsbcVerifyAndParseNotify 发生错误", fmt.Sprintf("验签解密失败,错误信息:%s", err.Error()))
return
}
return result, nil
}