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

265 lines
8.2 KiB
Go

package rchgutil
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"reflect"
"sort"
"strconv"
"strings"
"time"
"91porn-server/app/appg"
"91porn-server/common/httputil"
"91porn-server/common/log"
"91porn-server/web/webg"
)
var zfc = config{
MercID: "191309702",
AppSecret: "oaha2s6ed67buc2rpy7of1p3mj17jpqwa0i0n3fjy633et7thwzmv1s3zbwaim9z2o4r3km799u8lp7a1luh1vpd350bazq5bmph66ffm3p9u8trow5lzmtmsx6b66rkya1up22x1rbjvhuby7wkpcidix064ay25d6ri48boo5f5fc0m05oi558d154qw6816p7ym1h52r2gsbndo6pi5i7qgonqp7aagkrh5ar3k3ircgvunqmcfbd4z45k9nz",
ExeUrl: "http://www.518006.com/Pay_Index.html",
QueryUrl: "http://www.518006.com/Pay_Trade_query.html",
NotifyUrl: "/3rd/defray/callback/zhongfu",
CallbackURL: "/refuse",
VerifySecret: "muykk2dlwnmvsn5m5eg5ajs8vhfvfdihqqc2t2rd0297h2bwnkhf2jrk6qveffog038jsfsk4js0yjmkb9ydeijdtjbq98ouh8eqm04gvva3ql6mo0yknaq1v377mw1j",
}
// ZhongFu 充值订单请求体
type ZhongFu struct {
Version string `json:"pay_version" sign:"1"`
MercID string `json:"pay_memberid" sign:"1"` //商户编号
Type string `json:"pay_bankcode" sign:"1"`
TradeNo string `json:"pay_orderid" sign:"1"` //商户订单号
Money string `json:"pay_amount" sign:"1"` // 充值⾦额
CallbackUrl string `json:"pay_callbackurl" sign:"1"` //支付成功后的跳转地址
NotifyURL string `json:"pay_notifyurl" sign:"1"` // 回调地址
ProductName string `json:"pay_productname"` // 商品信息
UserIP string `json:"pay_ip" sign:"1"` //用户ip
SignType string `json:"pay_signtype" sign:"1"` //签名类型
Charset string `json:"pay_inputcharset" sign:"1"`
Time string `json:"pay_applydate" sign:"1"`
PayFormat string `json:"pay_retformat"` //参数类型
Sign string `json:"pay_md5sign" ` // 签名
PayMethod string `json:"pay_method,omitempty"` // 支付类型
}
// ZhongFuRes 回调函数参数model
type ZhongFuRes struct {
Version string `json:"version" form:"version" sign:"1"`
MercID string `json:"memberid" form:"memberid" sign:"1"` //商户编号
TradeNo string `json:"orderid" form:"orderid" sign:"1"` //商户订单号
OID string `json:"transaction_id" form:"transaction_id" sign:"1"` //支付平台订单号
PayMoney string `json:"amount" form:"amount" sign:"1"` //订单到账实际金额
PayTime string `json:"datetime" form:"datetime" sign:"1"` //交易时间
Code string `json:"returncode" form:"returncode" sign:"1"`
Sign string `json:"sign" form:"sign"` //签名
}
// ToPay 支付发起
func (this *ZhongFu) ToPay() (payUrl string, err error) {
defer func(err *error, payUrl string, obj interface{}) {
if err == nil && payUrl == "" {
fmt.Printf("zhongfu ToPay Http.PostJson fail error:data %+v;\r\n", this)
}
}(&err, payUrl, this)
var errlog string
this.Fill()
var msg struct {
PayURL string `json:"payurl"`
Msg string `json:"msg"`
Data interface{} `json:"data"`
Status string `json:"status"`
}
code, err := httputil.DefaultClientPostWithRespWithProxy(appg.ProxyCfg, &msg, this.GetURL(), this.GetHeader(), this.GetBody())
if err != nil {
errlog = fmt.Sprintf("zhongfu ToPay Http.PostJson fail error:%+v/,data:%+v;", err, this)
log.Error(errlog)
err = errors.New(errlog)
return
}
if code != http.StatusOK {
errlog = fmt.Sprintf("zhongfu ToPay Http.PostJson fail error:%+v/,data:%+v;", err, code)
log.Error(errlog)
err = errors.New(errlog)
return
}
if msg.Msg != "success" {
errlog = fmt.Sprintf("zhongfu topay response err :%+v:", msg)
err = errors.New(errlog)
log.Error(errlog)
return
}
payUrl = msg.PayURL
return
}
// QueryOrder 订单状态查询发起
func (this *ZhongFuRes) QueryOrder() (payTime time.Time, err error) {
msg := msgModel{}
body := make(map[string]string)
body["partner_id"] = zfc.MercID
body["partner_order"] = this.TradeNo
body["sign"] = md5Sign("partner_id=" + zfc.MercID + "&partner_order=" + this.TradeNo + "&key=" + zfc.AppSecret)
code, err := httputil.DefaultClientPostWithRespWithProxy(webg.ProxyCfg, &msg, zfc.QueryUrl, nil, body)
if err != nil || code != 200 {
log.Error(fmt.Sprintf("zhongfu QueryOrder http.Get fail error:%+v:", err))
return
}
if msg.Code != 1 {
err = errors.New("zhongfu QueryOrder fail")
log.Error(fmt.Sprintf("zhongfu QueryOrder http.Get fail error:%+v:", msg))
return
}
loc, _ := time.LoadLocation("Local")
payTime, err = time.ParseInLocation("2006-01-02 15:04:05", msg.Data.PayTime, loc)
return
}
// Fill 补全配置信息和签名信息
func (this *ZhongFu) Fill() {
this.Version = "v2.3.5"
this.MercID = this.GetMercID()
this.NotifyURL = this.GetNotifyURL()
this.CallbackUrl = this.GetCallBackURL()
if this.UserIP == "" {
this.UserIP = genIpaddr()
}
this.Type = this.PayMethod
this.PayMethod = ""
this.Charset = "UTF-8"
this.SignType = "MD5"
this.PayFormat = "json"
this.Sign = this.sign()
}
// sign 签名
func (this *ZhongFu) sign() (sign string) {
ss := this.ToStringSlice()
sort.Sort(&ss)
var buf bytes.Buffer
for k, v := range ss {
if k == 0 {
buf.WriteString(v)
} else {
buf.WriteString("&")
buf.WriteString(v)
}
}
buf.WriteString("&key=")
buf.WriteString(this.GetAppSecret())
log.Info(fmt.Sprintf("ZhongFu topay sign :%s", buf.String()))
return strings.ToUpper(md5Sign(buf.String()))
}
// sign 签名
func (this *ZhongFuRes) ToSign() (sign string) {
ss := this.ToStringSlice()
sort.Sort(&ss)
var buf bytes.Buffer
for _, v := range ss {
buf.WriteString(v)
buf.WriteString("&")
}
buf.WriteString("key=")
buf.WriteString(zfc.VerifySecret)
log.Info(fmt.Sprintf("ZhongFu callback sign:%s", buf.String()))
str := buf.String()
sign = strings.ToUpper(md5Sign(str))
return
}
// ToStringSlice 转化为stirng切片切片
func (this *ZhongFu) ToStringSlice() StringList {
t := reflect.TypeOf(*this)
v := reflect.ValueOf(*this)
data := make([]string, 0, v.NumField())
for k := 0; k < v.NumField(); k++ {
jsonTag, _ := t.Field(k).Tag.Lookup("json")
signTag, _ := t.Field(k).Tag.Lookup("sign")
fv := v.Field(k).Type()
if signTag == "1" {
switch fv.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
data = append(data, jsonTag+"="+strconv.FormatInt(v.Field(k).Int(), 10))
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
data = append(data, jsonTag+"="+strconv.FormatUint(v.Field(k).Uint(), 10))
case reflect.String:
data = append(data, jsonTag+"="+v.Field(k).String())
}
}
}
return data
}
// ToStringSlice 转化为stirng切片切片
func (this *ZhongFuRes) ToStringSlice() StringList {
t := reflect.TypeOf(*this)
v := reflect.ValueOf(*this)
data := make([]string, 0, v.NumField())
for k := 0; k < v.NumField(); k++ {
jsonTag, _ := t.Field(k).Tag.Lookup("json")
signTag, _ := t.Field(k).Tag.Lookup("sign")
if signTag == "1" && v.Field(k).String() != "" {
data = append(data, jsonTag+"="+v.Field(k).String())
}
}
return data
}
// GetBody 获取请求body
func (this *ZhongFu) GetBody() interface{} {
jsonStr, err := json.Marshal(this)
if err != nil {
log.Info(fmt.Sprintf("ZhongFu GetBody json.Marshal is fail error:%+v/data:%+v", err, this))
}
log.Info(fmt.Sprintf("==================%+v", string(jsonStr)))
return jsonStr
}
// GetHeader 获取请求头信息
func (*ZhongFu) GetHeader() map[string]string {
return map[string]string{}
}
// GetURL 获取请求地址
func (*ZhongFu) GetURL() string {
return zfc.ExeUrl
}
// GetQueryURL 获取请求地址
func (*ZhongFu) GetQueryURL() string {
return zfc.QueryUrl
}
// GetLowAndUpperURL 获取请求地址
func (*ZhongFu) GetLowAndUpperURL() string {
return zfc.LowAndUpperURL
}
// GetCallBackURL 获取回掉函数
func (*ZhongFu) GetNotifyURL() string {
if appg.Conf != nil {
return appg.Conf.URL.LocalWebUrl + zfc.NotifyUrl
}
return webg.Conf.URL.LocalAppUrl + zfc.NotifyUrl
}
// GetCallBackURL 获取回掉函数
func (*ZhongFu) GetCallBackURL() string {
return zfc.CallbackURL
}
// GetMercID 获取商户编号
func (*ZhongFu) GetMercID() string {
return zfc.MercID
}
// GetAppSecret 获取app签名密钥
func (*ZhongFu) GetAppSecret() string {
return zfc.AppSecret
}