Files
huangguo_server/common/rchgutil/yongliwanshun.go
T
rootandClaude Opus 5 8679200f41 Initial commit
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 13:57:10 +08:00

208 lines
6.4 KiB
Go

package rchgutil
import (
"crypto/rc4"
"encoding/json"
"errors"
"fmt"
"net/http"
"strconv"
"time"
"91porn-server/app/appg"
"91porn-server/common/httputil"
"91porn-server/common/log"
)
var ylws = config{
MercID: "10105",
AppSecret: "DA1C5476400B1D",
ExeUrl: "http://x.aee7.com/gateway/index/checkpoint.do?",
NotifyUrl: "/3rd/defray/callback/rchg/",
}
// 订单请求体
type WsylInfo struct {
AccountId string `json:"account_id"` // 商户ID
ContentType string `json:"content_type"` // 返回的网页类型
Thoroughfare string `json:"thoroughfare"` // 通道
Type string `json:"type"` // 支付类型
OutTradeNo string `json:"out_trade_no"` // 商户订单号
Robin string `json:"robin"` // 轮训
UseCity string `json:"use_city"` // 按地区收款
Amount string `json:"amount"` // 支付金额
CallbackUrl string `json:"callback_url"` // 异步通知地址
SuccessUrl string `json:"success_url"` // 支付成功后网页自动跳转地址
ErrorUrl string `json:"error_url"` // 支付失败时,或支付超时后网页自动跳转地址
Sign string `json:"sign"` // 签名 必填
}
type WsylMsgData struct {
OrderId string `json:"order_id"`
Qrcode string `json:"qrcode"`
}
type WsylMsg struct {
Code int `json:"code"` // 交易返回码,返回SUCCESS 表示交易成功(不代表最终结果),
Msg string `json:"msg"` // 签名
Data interface{} `json:"data,omitempty"`
}
// 回调函数参数
type WsylResultRes struct {
AccountName string `form:"account_name" json:"account_name"` // 商户登录名
PayTime string `form:"pay_time" json:"pay_time"` // 支付成功的时间戳(10位)
Status string `form:"status" json:"status"` // 状态
Amount string `form:"amount" json:"amount"` // 订单到账实际金额
OutTradeNo string `form:"out_trade_no" json:"out_trade_no"` // 订单信息,在发起订单时附加的信息,如用户名,充值订单号等字段参数
TradeNo string `form:"trade_no" json:"trade_no"` // 交易流水号,由系统生成的交易流水号
Fees string `form:"fees" json:"fees"` // 手续费,本次回调过程产生的手续费用(已经在平台账户中扣除)
Sign string `form:"sign" json:"sign"` // 签名
CallbackTime string `form:"callback_time" json:"callback_time"` // 回调时间,在回调时产生的时间戳(10位)
Type string `form:"type" json:"type"` // 支付类型
AccountKey string `form:"account_key" json:"account_key"` // 商户KEY
}
// ToPay 支付发起
func (wyi *WsylInfo) toPay() (res RchgMsg, err error) {
var errLog string
msg := WsylMsg{}
wyi.fill()
code, err := httputil.DefaultClientPostJsonWithResp(&msg, ylws.ExeUrl, wyi.getHeader(), wyi.getBody())
if err != nil {
errLog = fmt.Sprintf("Wsyl ToPay requset fail \nerror:%+v\n\ndata:%+v;", err, wyi)
log.Error(errLog)
err = errors.New(errLog)
return
}
if code != http.StatusOK {
errLog = fmt.Sprintf("Wsyl ToPay response status exception;\nstatus %+v;", code)
log.Error(errLog)
err = errors.New(errLog)
return
}
if msg.Code != 200 {
errLog = fmt.Sprintf("Wsyl ToPay be rejected;\n msg:%+v:", msg)
err = errors.New(errLog)
log.Error(errLog)
return
}
var data WsylMsgData
bytes, err := json.Marshal(msg.Data)
if err != nil {
errLog = fmt.Sprintf("Wsyl payUrl urlDecode fail \nerror:%+v;", err)
log.Error(errLog)
err = errors.New(errLog)
return
}
if err = json.Unmarshal(bytes, &data); err != nil {
errLog = fmt.Sprintf("Wsyl payUrl urlDecode fail \nerror:%+v;", err)
log.Error(errLog)
err = errors.New(errLog)
return
}
res.PayUrl = data.Qrcode
res.Mode = "url"
res.OID = data.OrderId
return
}
// Notify 回调函数
func (this *WsylResultRes) Notify() (RchgBack, error) {
r := RchgBack{}
if this.SignRes() != this.Sign {
log.Error(fmt.Sprintf("Wsyl callback sign verify fail ,data:%+v", this))
return r, errors.New("check sign fail")
}
if this.PayTime == "" {
return r, errors.New("querry order err,no payTime")
}
sec, err := strconv.ParseInt(this.PayTime, 10, 64)
if err != nil {
log.Error("time.ParseInLocation failed", log.Any("TradeNo", this.TradeNo), log.E(err))
return r, err
}
paymentAt := time.Unix(sec, 0)
payMoneyf, err := strconv.ParseFloat(this.Amount, 64)
if err != nil {
log.Error(fmt.Sprintf("Wsyl callback ParseFloat fail data:%+v:", this))
return r, fmt.Errorf("invalid payMoney %s", this.Amount)
}
r.PayMoney = int64(payMoneyf * 100)
r.PaymentAt = paymentAt
r.TransNo = this.OutTradeNo
r.OID = this.TradeNo
r.Code = 400
if this.Status == "success" {
r.Code = 200
}
return r, nil
}
func (this *WsylResultRes) Success() string {
return "success"
}
// 补全配置信息和签名信息
func (wyi *WsylInfo) fill() {
wyi.AccountId = ylws.MercID
wyi.ContentType = "json"
wyi.Thoroughfare = "paofen_auto"
wyi.Type = "71"
wyi.Robin = "2"
wyi.UseCity = "2"
wyi.CallbackUrl = wyi.getNotifyURL()
wyi.SuccessUrl = wyi.getNotifyURL()
wyi.ErrorUrl = wyi.getNotifyURL()
wyi.Sign = wyi.signReq()
}
// 充值请求签名
func (wyi *WsylInfo) signReq() (sign string) {
return DealSign(ylws.AppSecret, wyi.Amount, wyi.OutTradeNo)
}
func DealSign(key_id string, amount string, out_trade_no string) (sign string) {
var data = amount + out_trade_no
md5Str := md5Sign(data)
c, err := rc4.NewCipher([]byte(key_id))
if err != nil {
// log.Fatalln(err)
return
}
src := []byte(md5Str)
dst := make([]byte, len(src))
c.XORKeyStream(dst, src)
fmt.Println(string(src), string(dst))
rc4Str := md5Sign(string(dst))
return rc4Str
}
// 充值成功回调签名
func (wyc *WsylResultRes) SignRes() (sign string) {
return DealSign(ylws.AppSecret, wyc.Amount, wyc.OutTradeNo)
}
// 获取请求body
func (wyi *WsylInfo) getBody() interface{} {
m := make(map[string]string)
jsonStr, err := json.Marshal(wyi)
if err != nil {
log.Info(fmt.Sprintf("WSYL GetBody json.Marshal is fail error:%+v/data:%+v", err, wyi))
}
sstr := string(jsonStr)
log.Info(fmt.Sprintf("==================%+v", sstr))
_ = json.Unmarshal(jsonStr, &m)
return m
}
// 获取请求头
func (wyi *WsylInfo) getHeader() map[string]string {
return nil
}
// 获取回掉函数
func (wyi *WsylInfo) getNotifyURL() (url string) {
return appg.Conf.URL.LocalWebUrl + ylws.NotifyUrl + YongLiWanShun
}