package pay

import (
	"bytes"
	"context"
	"crypto"
	"crypto/md5"
	"crypto/rand"
	"crypto/rsa"
	"crypto/tls"
	"crypto/x509"
	b64 "encoding/base64"
	"encoding/json"
	"encoding/pem"
	"encoding/xml"
	"errors"
	"fmt"
	"github.com/rs/zerolog/log"
	"github.com/wechatpay-apiv3/wechatpay-go/core"
	"github.com/wechatpay-apiv3/wechatpay-go/core/option"
	"github.com/wechatpay-apiv3/wechatpay-go/services/refunddomestic"
	"github.com/wechatpay-apiv3/wechatpay-go/services/transferbatch"
	"go-admin/tools/config"
	"io"
	"os"

	//"github.com/wechatpay-apiv3/wechatpay-go/utils"
	wechatpayutils "github.com/wechatpay-apiv3/wechatpay-go/utils"
	"go-admin/logger"
	"io/ioutil"
	"net/http"
	"sort"
	"strings"
	"time"
)

const (
	//公共参数
	SpbilCreateIp         = "113.97.33.19"
	NonceStringLength     = 32
	WechatUnifiedOrderUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder"
	WxTransferUrl         = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers"
	//app端微信支付
	WechatAppId = "wx533b2ea6660ee3ad"
	//WechatMchId           = "1493640582" // 1499688752
	WechatMchId = "1499688752" // 1499688752
	//WechatPayKey          = "cdbTz6lKwBfqUHvJ4sVrD8Idz2dVOGMe"
	WechatPayKey = "wRro53HnVVlsJQpkfcs200eyaeSvQPog"
	CRSTaCode    = "0002" //CRS微信支付入账代码，必须为消费代码
	APP_TRADE    = "APP"  //APP支付
	WxCheckName  = "NO_CHECK"
	//"app_id": "wxb20ee1a562e56453",
	//"app_secret": "26e2a1203ad8403891a78a56a37cade5",
	//"app_mchId": "1517772711",
	//"app_mchSecret": "BCHkQGyEKrgHQIfMSi7E4udkt9Ua6AZV"

	//"wx": {
	//"app_id": "wxff888972e97ff2ef",
	//"app_secret": "3d7335cf0b9fa1d70aa7eb079526ebf0",
	//"app_mchId": "1494688302",
	//"app_mchSecret": "aaff113c243c47e1cf09af30fe3a6d2b"
	//},

	//callbackUrl = "https://zouzou.api.wawazhuawawa.com/api/v1/wxpay/notice"
	//WxCertFile  = "/root/zouzou/configs/pro/1494688302_20190624_cert/apiclient_cert.p12"
	//WxKeyFile   = "/root/zouzou/configs/pro/1494688302_20190624_cert/apiclient_key.pem"
	//rootCaFile  = "/root/zouzou/configs/pro/1494688302_20190624_cert/apiclient_cert.pem"

	WxKeyFile    = "./config/merchant/apiclient_key.pem"
	WxRootCaFile = "./config/merchant/apiclient_cert.pem"

	//WxKeyFile    = "/www/wwwroot/dev.admin.deovo.com/admin_server/go-admin/config/apiclient_key.pem"
	//WxRootCaFile = "/www/wwwroot/dev.admin.deovo.com/admin_server/go-admin/config/apiclient_cert.pem"

	WxAppId     = "wx806c079463b5b56c"
	WxAppSecret = "3d7335cf0b9fa1d70aa7eb079526ebf0"
	//WxAppMchId     = "1494688302"
	WxAppMchId     = "1609877389"
	WxAppMchSecret = "DeovoMingHuiRengTianTang45675456"

	UnifiedOrderUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder"
	HmPayApiUrl     = "https://hmpay.sandpay.com.cn/gateway/api"
	PemBegin        = "-----BEGIN RSA PRIVATE KEY-----\n"
	PemEnd          = "\n-----END RSA PRIVATE KEY-----"

	TimeFormat  = "2006-01-02 15:04:05"
	clientIp    = "39.108.188.218" // 小程序服务器
	clientIpDev = "112.33.14.191"  // 移动云服务器

	// HmPayMerchantId 明慧帐户
	HmPayMerchantId = "664403000030115"
	HmPubKey        = `MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDzGVH0Fxpb2M48U1BWr6lpNs2W3VHqtjO8X5RqWjtTwpQVKo8dqaiAGxVbsdnefPpsbI5l9rKquRAOJhWFU07hxSUgXZOk55QQmll03MBgRDXLgxyKfycLLQwhsCJAzDIWC7IWgok/RHV9m9AV2GbQxWBl+7iDE4prcbpgG8Z0HwIDAQAB`
	HmPubKeyFp      = "./config/hm_pay/private_key.pem"
	TestHmPubKeyFp  = "/Users/max/Documents/code/deovo/mh_goadmin_server/config/hm_pay/private_key.pem"

	// HmPayMerchantIdSwitch 任天堂项目-对私账户(密钥20240701203620)
	HmPayMerchantIdSwitch = "664403000021193"
	HmPubKeySwitch        = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCDA4g8VFWIxEbOzxYC8ZIOgaOsLWK4Y5k9D8GwJ1Gige79LbTxbe3PH12KMc59DpCR1PnIDwlYWjIE7mZZAHgImXs0pSFihvlNS9srWk2uPlEXXQjjIZ3mnPoXtNhU0x5cYdkB8jtijcYMSGwKmdrIvpvPX3MrDKOX6dJ1T4ll+QIDAQAB"
	HmPubKeySwitchFp      = "./config/hm_pay/switch_private_key.pem"
	TestHmPubKeySwitchFp  = "/Users/max/Documents/code/deovo/mh_goadmin_server/config/hm_pay/switch_private_key.pem"

	// HmPayMerchantIdSwitchPub 任天堂项目-对公账户(密钥20240819161949)
	HmPayMerchantIdSwitchPub = "664403000021225"
	HmPubKeySwitchPub        = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCBsfp+BrCGD39noWjW4z0VvvsFCWzU8vhAWlwGo/dkPxgQLXBNaTApUpavbQ6m/S0x5hQjcKwQ3UrJLDV70SAqPuO3QP0iagMKo2M6ROCO69L06In4gbqTTtTOb/1xpkbsVHd/9Wy/fyxreg1LY+MLzysH+OHAjjjiAYVL4e765QIDAQAB"
	HmPubKeySwitchPubFp      = "./config/hm_pay/switch_pub_private_key.pem"
	TestHmPubKeySwitchPubFp  = "/Users/max/Documents/code/deovo/mh_goadmin_server/config/hm_pay/switch_pub_private_key.pem"

	// HmPayMerchantIdJBL 哈曼项目-对私账户(密钥20240820145322)
	HmPayMerchantIdJBL = "664403000021330"
	HmPubKeyJBL        = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCBhzboiNtCxDF3QXdPGx5aS2UjXSqq1p2JsIe+PhCWLdaNHoQxzTS0s41KuWbSDpSmtUhutBJZ1QBy+84iLmLKJ5E7UfUIGbrI309hJLQxQey655wWYBtkOVpq6aozjjnnjQjDbYG1WuFmLA03mzQ51VLr4555ioo70hredjLaVQIDAQAB"
	HmPubKeyJBLFp      = "./config/hm_pay/jbl_private_key.pem"
	TestHmPubKeyJBLFp  = "/Users/max/Documents/code/deovo/mh_goadmin_server/config/hm_pay/jbl_private_key.pem"

	// HmPayMerchantIdJBLPub 哈曼项目-对公账户
	HmPayMerchantIdJBLPub = "664403000021340"
	HmPubKeyJBLPub        = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDIjqYgPO1kj3NI0WEfOCnKYUHu4EkARnbiJ2FKosajpP8eceaL1u4JOelNG+RN7cldvmWEtefZCPNOHAHddQLfEnRZ3xyzdRdV0A3vXykyY6UMWgRlPnHOslAm8OUpOWubDzQTmfr88R38EUrHG4HYvRVmQb/s/LQjsuS863vSbwIDAQAB"
	HmPubKeyJBLPubFp      = "./config/hm_pay/jbl_pub_private_key.pem"
	TestHmPubKeyJBLPubFp  = "/Users/max/Documents/code/deovo/mh_goadmin_server/config/hm_pay/jbl_pub_private_key.pem"

	// mchID 小程序-明慧帐户
	mchID                      = "1609877389"                               // 商户号
	mchCertificateSerialNumber = "7540301D8FD52CCF7D6267DCF7CD2BC0AB467EFF" // 商户证书序列号
	mchAPIv3Key                = "DeovoMingHuiRengTianTang45675123"         // 商户APIv3密钥

	// MchIDDw 小程序-迪为帐户
	MchIDDw                      = "1494954322"                               // 商户号
	MchCertificateSerialNumberDw = "5D98B7F99C24BFD8649E2045635AFBBCDD5B29C1" // 商户证书序列号
	MchAPIv3KeyDw                = "hTCTqF9jHsWlFOO8ZuL05BDo2UlrJwVv"         // 商户APIv3密钥
)

type WxTransferResp struct {
	ReturnCode     string `xml:"return_code,CDATA"`
	ReturnMsg      string `xml:"return_msg,CDATA"`
	ResultCode     string `xml:"result_code,CDATA"`
	ErrCodeDes     string `xml:"err_code_des,CDATA"`
	PartnerTradeNo string `xml:"partner_trade_no,CDATA"`
	PaymentNo      string `xml:"payment_no,CDATA"`
}

// https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2
type WxTransferReq struct {
	XMLName        xml.Name `xml:"xml"`                        //xml标签
	MchAppid       string   `xml:"mch_appid" json:"mch_appid"` //微信分配的小程序ID，必须
	MchId          string   `xml:"mchid" json:"mchid"`         //微信支付分配的商户号，必须
	DeviceInfo     string   `xml:"device_info" json:"device_info"`
	NonceStr       string   `xml:"nonce_str" json:"nonce_str"`               //随机字符串，必须
	Sign           string   `xml:"sign" json:"sign"`                         //签名，必须 	//"HMAC-SHA256"或者"MD5"，非必须，默认MD5
	PartnerTradeNo string   `xml:"partner_trade_no" json:"partner_trade_no"` //CRS订单号，必须
	OpenId         string   `xml:"openid" json:"openid"`                     //微信用户唯一标识，必须
	CheckName      string   `xml:"check_name" json:"check_name"`
	ReUserName     string   `xml:"re_user_name" json:"re_user_name"`
	Amount         string   `xml:"amount" json:"amount"`
	Desc           string   `xml:"desc" json:"desc"`
	SpbillCreateIp string   `xml:"spbill_create_ip" json:"spbill_create_ip"`
	//SignType       string   `xml:"sign_type" json:"sign_type"` //"HMAC-SHA256"或者"MD5"，非必须，默认MD5
}

func GenTradeNo() string {
	now := time.Now().Local()
	strTime := fmt.Sprintf("%04d%02d%02d%02d%02d%02d", now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second())
	tradeNO := strTime + RandomNumString(100000, 999999)
	return tradeNO
}

// Transfer 给用户打款
func Transfer(amount uint32, openId string, desc string) (*WxTransferResp, error) {
	tradeNO := GenTradeNo()
	nonce := GenRandStr(NonceStringLength)

	req := WxTransferReq{
		MchAppid: WxAppId,
		MchId:    WxAppMchId,
		NonceStr: nonce,
		Sign:     "",
		//SignType:       "MD5",
		PartnerTradeNo: tradeNO,
		OpenId:         openId,
		CheckName:      WxCheckName,
		Amount:         fmt.Sprintf("%d", amount),
		//Desc:           "押金退款",
		Desc:           desc,
		SpbillCreateIp: SpbilCreateIp,
	}

	wxResp := WxTransferResp{}

	//生成签名
	m, err := struct2Map(req)
	if err != nil {
		logger.Error(err.Error())
		return nil, err
	}

	sign, err := GenWechatPaySign(m, WxAppMchSecret)
	if err != nil {
		logger.Error(err.Error())
		return nil, err
	}
	req.Sign = strings.ToUpper(sign)

	payload, err := xml.Marshal(&req)
	if err != nil {
		logger.Error(err.Error())
		return nil, err
	}

	request, err := newPostRequest(WxTransferUrl, string(payload))
	if err != nil {
		logger.Error(err.Error())
		return nil, err
	}
	defer request.Body.Close()
	logger.Info("证书路径:", logger.Field("WxRootCaFile", WxRootCaFile))
	logger.Info("证书路径:", logger.Field("WxKeyFile", WxKeyFile))
	client, err := newHttpClient(WxRootCaFile, WxKeyFile)
	if err != nil {
		logger.Error(err.Error())
		return nil, err
	}

	resp, err := client.Do(request)
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		logger.Error(err.Error())
		return nil, err
	}
	//logger.Info("Transfer resp = ", string(body))
	logger.Info("Transfer resp ", logger.Field("body", string(body)))
	err = xml.Unmarshal(body, &wxResp)
	if err != nil {
		logger.Error(err.Error())
		return nil, err
	}

	if wxResp.ReturnCode != "SUCCESS" || wxResp.ResultCode != "SUCCESS" {

		return nil, errors.New("Transfer fail")
	}

	return &wxResp, nil
}

func newHttpClient(certFile, keyFile string) (*http.Client, error) {
	//
	//cert, err := ioutil.ReadFile(certFile)
	//logger.Info("cert:",string(cert))
	//logger.Info("err:",err)
	//if err != nil {
	//	return nil, err
	//}
	//
	//key, err := ioutil.ReadFile(keyFile)
	//logger.Info("key:",string(key))
	//logger.Info("key:",err)
	//if err != nil {
	//	return nil, err
	//}

	//tlsCert, err := tls.X509KeyPair(cert, key)
	//logger.Info("tlsCert:",tlsCert)
	//logger.Info("err:",err)
	//if err != nil {
	//	return nil, err
	//}

	tlsCert, err := tls.LoadX509KeyPair(certFile, keyFile)
	if err != nil {
		return nil, err
	}

	conf := &tls.Config{
		Certificates: []tls.Certificate{tlsCert},
	}
	trans := &http.Transport{
		TLSClientConfig: conf,
	}
	client := &http.Client{
		Transport: trans,
	}

	return client, nil
}

//func newHttpsClient() (*http.Client, error) {
//	tlsCert, err := tls.LoadX509KeyPair(config.AppConfig.WxCertFile, config.AppConfig.WxKeyFile)
//	if err != nil {
//		logger.Error(err)
//		return nil, err
//	}
//
//	conf := &tls.Config{
//		Certificates: []tls.Certificate{tlsCert},
//	}
//	trans := &http.Transport{
//		TLSClientConfig: conf,
//	}
//	client := &http.Client{
//		Transport: trans,
//	}
//
//	return client, nil
//}

func newPostRequest(url string, content string) (*http.Request, error) {
	request, err := http.NewRequest("POST", url, strings.NewReader(content))
	if err != nil {
		return nil, err
	}

	request.Header.Set("Content-Type", "application/xml")

	return request, nil
}

func struct2Map(r interface{}) (s map[string]string, err error) {
	var temp map[string]interface{}
	var result = make(map[string]string)

	bin, err := json.Marshal(r)
	if err != nil {
		return result, err
	}

	if err := json.Unmarshal(bin, &temp); err != nil {
		return nil, err
	}
	for k, v := range temp {
		switch v2 := v.(type) {
		case string:
			result[k] = v2
		case uint, int8, uint8, int, int16, uint16, int32, uint32, int64, uint64:
			result[k] = fmt.Sprintf("%d", v2)
		case float32, float64:
			result[k] = fmt.Sprintf("%.0f", v2)
		}
	}

	return result, nil
}

func GenWechatPaySign(m map[string]string, payKey string) (string, error) {
	delete(m, "sign")
	var signData []string
	for k, v := range m {
		if v != "" && v != "0" {
			signData = append(signData, fmt.Sprintf("%s=%s", k, v))
		}
	}

	sort.Strings(signData)
	signStr := strings.Join(signData, "&")
	signStr = signStr + "&key=" + payKey

	logger.Info("签字符串1 :", logger.Field("sign", signStr))
	c := md5.New()
	_, err := c.Write([]byte(signStr))
	if err != nil {
		return "", err
	}

	signByte := c.Sum(nil)
	if err != nil {
		return "", err
	}

	return fmt.Sprintf("%x", signByte), nil
}

//const (
//	mchID                      string = "1609877389"                               // 商户号
//	mchCertificateSerialNumber string = "7540301D8FD52CCF7D6267DCF7CD2BC0AB467EFF" // 商户证书序列号
//	mchAPIv3Key                string = "DeovoMingHuiRengTianTang45675123"         // 商户APIv3密钥
//)

//微信商户
//商户ID：1609877389
//操作密码：456755
//密钥API：DeovoMingHuiRengTianTang45675456
//密钥APIv3: DeovoMingHuiRengTianTang45675123
//证书序列号：7540301D8FD52CCF7D6267DCF7CD2BC0AB467EFF

func WxSDKPay(uid uint32, wxName string) {
	// 使用 utils 提供的函数从本地文件中加载商户私钥，商户私钥会用来生成请求的签名
	//mchPrivateKey, err := utils.LoadPrivateKeyWithPath("/path/to/merchant/apiclient_key.pem")
	mchPrivateKey, err := wechatpayutils.LoadPrivateKeyWithPath("/Users/li/mh/mh_admin_server/app/admin/apis/pay/merchant/apiclient_key.pem")

	if err != nil {
		logger.Error(err.Error())
		return
	}

	ctx := context.Background()
	// 使用商户私钥等初始化 client，并使它具有自动定时获取微信支付平台证书的能力
	opts := []core.ClientOption{
		option.WithWechatPayAutoAuthCipher(mchID, mchCertificateSerialNumber, mchPrivateKey, mchAPIv3Key),
	}
	client, err := core.NewClient(ctx, opts...)
	if err != nil {
		logger.Errorf("new wechat pay client err:%s", err)
		return
	}

	//// 发送请求，以下载微信支付平台证书为例
	//// https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay5_1.shtml
	//svc := certificates.CertificatesApiService{Client: client}
	//resp, result, err := svc.DownloadCertificates(ctx)
	//logger.Errorf("status=%d resp=%s", result.Response.StatusCode, resp)

	//// 使用 utils 提供的函数从本地文件中加载商户私钥，商户私钥会用来生成请求的签名
	//mchPrivateKey, err := utils.LoadPrivateKeyWithPath("/path/to/merchant/apiclient_key.pem")
	//if err != nil {
	//	log.Print("load merchant private key error")
	//}

	//ctx := context.Background()
	//// 使用商户私钥等初始化 client，并使它具有自动定时获取微信支付平台证书的能力
	//opts := []core.ClientOption{
	//	option.WithWechatPayAutoAuthCipher(mchID, mchCertificateSerialNumber, mchPrivateKey, mchAPIv3Key),
	//}
	//client, err := core.NewClient(ctx, opts...)
	//if err != nil {
	//	log.Printf("new wechat pay client err:%s", err)
	//}

	svc := transferbatch.TransferBatchApiService{Client: client}

	resp, result, err := svc.InitiateBatchTransfer(ctx,
		transferbatch.InitiateBatchTransferRequest{
			Appid:       core.String("wxff888972e97ff2ef"),
			OutBatchNo:  core.String("plfk20200420131253415624"),
			BatchName:   core.String("押金退还"),
			BatchRemark: core.String("押金退还"),
			TotalAmount: core.Int64(40),
			TotalNum:    core.Int64(1),
			TransferDetailList: []transferbatch.TransferDetailInput{transferbatch.TransferDetailInput{
				Openid:         core.String("ohuHh4riVVPxwKHrYHsWwZRpxVMk"),
				OutDetailNo:    core.String("x23zy545Bd5436123145243"),
				TransferAmount: core.Int64(40),
				TransferRemark: core.String("押金退款"),
				//UserName: core.String("12341234"),
			}},
		},
	)

	if err != nil {
		// 处理错误
		logger.Errorf("call InitiateBatchTransfer err:%s", err)
	} else {
		// 处理返回结果
		logger.Errorf("status=%d resp=%s", result.Response.StatusCode, resp)
	}

}

type OrderRefund struct {
	OutTradeNo  string            `json:"out_trade_no"`
	OutRefundNo string            `json:"out_refund_no"`
	NotifyUrl   string            `json:"notify_url"`
	Amount      OrderRefundAmount `json:"amount"`
}

type OrderRefundAmount struct {
	Refund   uint32 `json:"refund"`
	Total    uint32 `json:"total"`
	Currency string `json:"currency"`
}

func TransactionOrderRefund(orderRefund OrderRefund, accountNum uint32) error {
	var cMchID, cMchCertificateSerialNumber, cMchAPIv3Key, privatePath string
	if accountNum == 2 { // 迪为帐户
		cMchID = MchIDDw
		cMchCertificateSerialNumber = MchCertificateSerialNumberDw
		cMchAPIv3Key = MchAPIv3KeyDw
		privatePath = "./config/dw_merchant/apiclient_key.pem"
	} else { // 明慧帐户
		cMchID = mchID
		cMchCertificateSerialNumber = mchCertificateSerialNumber
		cMchAPIv3Key = mchAPIv3Key
		privatePath = "./config/merchant/apiclient_key.pem"
	}

	//WxKeyFile = "./config/merchant/apiclient_key.pem"
	//mchPrivateKey, err := wechatpayutils.LoadPrivateKeyWithPath("/Users/li/mh/mh_admin_server/app/admin/apis/pay/merchant/apiclient_key.pem")
	//privatePathTest := "/www/wwwroot/dev.admin.deovo.com/admin_server/go-admin/config/merchant/apiclient_key.pem" // TODO 测试
	//privatePath := "/www/wwwroot/admin.deovo.com/admin_server/go-admin/config/merchant/apiclient_key.pem" // TODO 正式

	// 使用 utils 提供的函数从本地文件中加载商户私钥，商户私钥会用来生成请求的签名
	//mchPrivateKey, err := wechatpayutils.LoadPrivateKeyWithPath("./configs/merchant/apiclient_key.pem")
	mchPrivateKey, err := wechatpayutils.LoadPrivateKeyWithPath(privatePath)
	if err != nil {
		//log.Print("load merchant private key error")
		log.Error().Msg("load merchant private key error")
		return err
	}

	ctx := context.Background()
	// 使用商户私钥等初始化 client，并使它具有自动定时获取微信支付平台证书的能力
	opts := []core.ClientOption{
		option.WithWechatPayAutoAuthCipher(cMchID, cMchCertificateSerialNumber, mchPrivateKey, cMchAPIv3Key),
	}
	client, err := core.NewClient(ctx, opts...)
	if err != nil {
		//log.Printf("new wechat pay client err:%s", err)
		log.Error().Msgf("new wechat pay client err:%s", err.Error())
		return err
	}

	svc := refunddomestic.RefundsApiService{Client: client}
	resp, result, err := svc.Create(ctx,
		refunddomestic.CreateRequest{
			OutTradeNo:  core.String(orderRefund.OutTradeNo),
			OutRefundNo: core.String(orderRefund.OutRefundNo),
			Reason:      core.String("取消订单"),
			//NotifyUrl:   core.String("https://weixin.qq.com/api/v1/wxpay/notice"),
			NotifyUrl: core.String(orderRefund.NotifyUrl),
			Amount: &refunddomestic.AmountReq{
				Currency: core.String("CNY"),
				Refund:   core.Int64(int64(orderRefund.Amount.Refund)),
				Total:    core.Int64(int64(orderRefund.Amount.Total)),
			},
		},
	)

	if err != nil {
		// 处理错误
		var apiErr *core.APIError
		if errors.As(err, &apiErr) {
			log.Printf("call Create err: %s", apiErr.Message)
			return fmt.Errorf(apiErr.Message)
		} else {
			// 不是 APIError 类型，打印默认错误
			log.Printf("call Create err: %s", err.Error())
			return err
		}
	} else {
		// 处理返回结果
		log.Printf("status=%d resp=%s", result.Response.StatusCode, resp)
	}

	return nil
}

type (
	UnifiedOrderReq struct {
		XMLName        xml.Name `xml:"xml"`                                                //xml标签
		AppId          string   `xml:"appid" json:"appid"`                                 //微信分配的小程序ID，必须
		MchId          string   `xml:"mch_id" json:"mch_id"`                               //微信支付分配的商户号，必须
		DeviceInfo     string   `xml:"device_info" json:"device_info"`                     //微信支付填"WEB"，必须
		NonceStr       string   `xml:"nonce_str" json:"nonce_str"`                         //随机字符串，必须
		Sign           string   `xml:"sign" json:"sign"`                                   //签名，必须
		SignType       string   `xml:"sign_type" json:"sign_type"`                         //"HMAC-SHA256"或者"MD5"，非必须，默认MD5
		Body           string   `xml:"body" json:"body"`                                   //商品简单描述，必须
		Detail         string   `xml:"detail,omitempty" json:"detail,omitempty"`           //商品详细列表，使用json格式
		Attach         string   `xml:"attach" json:"attach"`                               //附加数据，如"贵阳分店"，非必须
		OutTradeNo     string   `xml:"out_trade_no" json:"out_trade_no"`                   //CRS订单号，必须
		FeeType        string   `xml:"fee_type,omitempty" json:"fee_type,omitempty"`       //默认人民币：CNY，非必须
		TotalFee       string   `xml:"total_fee" json:"total_fee"`                         //订单金额，单位分，必须
		SpbillCreateIp string   `xml:"spbill_create_ip" json:"spbill_create_ip"`           //支付提交客户端IP，如“123.123.123.123”，必须
		TimeStart      string   `xml:"time_start,omitempty" json:"time_start,omitempty"`   //订单生成时间，格式为yyyyMMddHHmmss，如20170324094700，非必须
		TimeExpire     string   `xml:"time_expire,omitempty" json:"time_expire,omitempty"` //订单结束时间，格式同上，非必须
		GoodsTag       string   `xml:"goods_tag,omitempty" json:"goods_tag,omitempty"`     //商品标记，代金券或立减优惠功能的参数，非必须
		NotifyUrl      string   `xml:"notify_url" json:"notify_url"`                       //接收微信支付异步通知回调地址，不能携带参数，必须
		TradeType      string   `xml:"trade_type" json:"trade_type"`                       //交易类型，小程序写"JSAPI"，必须
		LimitPay       string   `xml:"limit_pay,omitempty" json:"limit_pay,omitempty"`     //限制某种支付方式，非必须
		OpenId         string   `xml:"openid" json:"openid"`                               //微信用户唯一标识，必须
		ProfitSharing  string   `xml:"profit_sharing" json:"profit_sharing"`               //是否需要分账
	}

	UnifiedOrderResp struct {
		ReturnCode string `xml:"return_code"`
		ReturnMsg  string `xml:"return_msg"`
		AppId      string `xml:"appid"`
		MchId      string `xml:"mch_id"`
		DeviceInfo string `xml:"device_info"`
		NonceStr   string `xml:"nonce_str"`
		Sign       string `xml:"sign"`
		ResultCode string `xml:"result_code"`
		ErrCode    string `xml:"err_code"`
		ErrCodeDes string `xml:"err_code_des"`
		TradeType  string `xml:"trade_type"`
		PrepayId   string `xml:"prepay_id"`
	}
)

type HmJsPayUnifiedOrderReq struct {
	HmPayPublicPara
}

type HmPayPublicPara struct {
	AppId string `json:"app_id"`
	//SubAppId   string `json:"sub_app_id"`
	Method string `json:"method"`
	//Charset   string `json:"charset"`
	SignType  string `json:"sign_type"`
	Sign      string `json:"sign"`
	Timestamp string `json:"timestamp"`
	Nonce     string `json:"nonce"`
	//Version    string `json:"version"`
	//Format     string `json:"format"`
	BizContent string `json:"biz_content"`
}

// HmPayBizContent 统一预下单（JS）trade.create 业务请求参数
type HmPayBizContent struct {
	Body     string `json:"body"`
	MerAppId string `json:"mer_app_id"`
	//BuyerId    string `json:"buyer_id"`
	MerBuyerId string `json:"mer_buyer_id"`
	CreateIp   string `json:"create_ip"`
	CreateTime string `json:"create_time"`
	//DiscountInfo struct {
	//	DiscountableAmount float64 `json:"discountable_amount"`
	//} `json:"discount_info"`
	ExpireTime string `json:"expire_time"`
	//ExtendParams struct {
	//	AccessPartyCode string `json:"access_party_code"`
	//} `json:"extend_params"`
	//GoodsDetails []HmPayGoodsDetails `json:"goods_details"`
	//LimitPay  string `json:"limit_pay"`
	NotifyUrl string `json:"notify_url"`
	//OperatorId   string              `json:"operator_id"`
	OutOrderNo string `json:"out_order_no"`
	PayType    string `json:"pay_type"`
	PayWay     string `json:"pay_way"`
	StoreId    string `json:"store_id"`
	//TerminalId  string  `json:"terminal_id"`
	TotalAmount float64 `json:"total_amount"`
}

// HmPayBToCBizContent 刷卡支付（B扫C）trade.pay 业务请求参数
type HmPayBToCBizContent struct {
	AuthCode    string  `json:"auth_code"`
	CreateIp    string  `json:"create_ip"`
	CreateTime  string  `json:"create_time"`
	PayWay      string  `json:"pay_way"`
	TotalAmount float64 `json:"total_amount"`
	OutOrderNo  string  `json:"out_order_no"`
	Body        string  `json:"body"`
	StoreId     string  `json:"store_id"`
	TerminalId  string  `json:"terminal_id"`
	NotifyUrl   string  `json:"notify_url"`
}

// HmPayBToCOrderDetail 刷卡支付（B扫C）trade.pay 响应业务参数
type HmPayBToCOrderDetail struct {
	SubCode        string  `json:"sub_code"`         // 业务返回码
	SubMsg         string  `json:"sub_msg"`          // 业务返回信息
	PayWay         string  `json:"pay_way"`          // 支付方式 AUTO情况下，条码的类型
	BankWay        string  `json:"bank_way"`         // 银行通道
	OutOrderNo     string  `json:"out_order_no"`     // 商户订单号
	PlatTrxNo      string  `json:"plat_trx_no"`      // 平台交易流水号
	BankOrderNo    string  `json:"bank_order_no"`    // 银行订单号，平台送给渠道的商户订单号
	BankTrxNo      string  `json:"bank_trx_no"`      // 银行流水号，渠道返回给平台的流水号，订单成功情况下存在
	BuyerId        string  `json:"buyer_id"`         // 买家ID，付款方唯一标识
	SuccessTime    string  `json:"success_time"`     // 支付成功时间，格式yyyyMMddHHmmss
	TotalAmount    float64 `json:"total_amount"`     // 订单总金额
	SettleAmount   float64 `json:"settle_amount"`    // 商户可结算金额，订单金额-商户手续费
	BuyerPayAmount float64 `json:"buyer_pay_amount"` // 买家付款金额，买家实际付款的金额，订单金额-优惠金额
	ReqReserved    string  `json:"req_reserved"`     // 商户自定义字段
}

// HmPayTradeQueryContent 订单查询 trade.query 业务请求参数
type HmPayTradeQueryContent struct {
	OrderCreateTime string `json:"order_create_time,omitempty"` // 订单创建时间yyyyMMddHHmmss；当仅上送out_order_no需上送，若不上送，默认当天
	OutOrderNo      string `json:"out_order_no"`                // 商户订单号,订单号三选一必填
	PlatTrxNo       string `json:"plat_trx_no,omitempty"`       // 平台交易流水号
	BankOrderNo     string `json:"bank_order_no,omitempty"`     // 银行订单号
}

// HmPayTradeQueryResp 订单查询 trade.query 业务响应参数
type HmPayTradeQueryResp struct {
	SubCode             string  `json:"sub_code"`              // 业务返回码
	SubMsg              string  `json:"sub_msg"`               // 业务返回信息
	IsCancel            string  `json:"is_cancel"`             // 是否已撤销 true/false
	IsFundAuthPay       string  `json:"is_fund_auth_pay"`      // 预授权冻结是否已完成 true/false
	IsRefund            string  `json:"is_refund"`             // 是否有退款 true/false
	RefundSuccessAmount float64 `json:"refund_success_amount"` // 成功退款金额，单位元
	TotalAmount         float64 `json:"total_amount"`          // 订单总金额
	OutOrderNo          string  `json:"out_order_no"`          // 商户订单号
	PlatTrxNo           string  `json:"plat_trx_no"`           // 平台交易流水号
	BankOrderNo         string  `json:"bank_order_no"`         // 银行订单号
	BankTrxNo           string  `json:"bank_trx_no"`           // 银行流水号
	BuyerID             string  `json:"buyer_id"`              // 买家ID
	SuccessTime         string  `json:"success_time"`          // 支付成功时间，格式yyyyMMddHHmmss
	SettleAmount        float64 `json:"settle_amount"`         // 商户可结算金额，订单金额-商户手续费
	PayWayCode          string  `json:"pay_way_code"`          // 用户使用的交易方式，如WECHAT，ALIPAY，UNIONPAY
	PayModeCode         string  `json:"pay_mode_code"`         // 用户使用的支付模式，如扫码支付PAY_SCAN
	BankWayCode         string  `json:"bank_way_code"`         // 银行通道
	BuyerPayAmount      float64 `json:"buyer_pay_amount"`      // 买家付款金额，买家实际付款的金额，订单金额-优惠金额
	ReqReserved         string  `json:"req_reserved"`          // 商户自定义字段
}

// HmPayTradeCancelContent 订单撤销 trade.cancel 业务请求参数
type HmPayTradeCancelContent struct {
	OutOrderNo  string `json:"out_order_no"`            // 商户订单号,订单号三选一必填
	PlatTrxNo   string `json:"plat_trx_no,omitempty"`   // 平台交易流水号
	BankOrderNo string `json:"bank_order_no,omitempty"` // 银行订单号
}

// HmPayTradeCancelResp 订单撤销 trade.cancel 业务响应参数
type HmPayTradeCancelResp struct {
	SubCode         string `json:"sub_code"`           // 业务返回码
	SubMsg          string `json:"sub_msg"`            // 业务返回信息
	Action          string `json:"action"`             // 本次撤销触发的动作 CLOSE REFUND UNKNOW
	CancelPlatTrxNo string `json:"cancel_plat_trx_no"` // 撤销平台流水号
	ReqReserved     string `json:"req_reserved"`       // 商户自定义字段
}

// HmPayTradeRefundContent 订单退款 trade.refund 业务请求参数
type HmPayTradeRefundContent struct {
	OrderCreateTime string  `json:"order_create_time,omitempty"` // 订单创建时间，格式：yyyyMMddHHmmss（可选，但与 out_order_no 联动必填）
	OutOrderNo      string  `json:"out_order_no,omitempty"`      // 商户订单号，三选一必填之一
	PlatTrxNo       string  `json:"plat_trx_no,omitempty"`       // 平台交易流水号，三选一必填之一
	BankOrderNo     string  `json:"bank_order_no,omitempty"`     // 银行订单号，三选一必填之一
	RefundAmount    float64 `json:"refund_amount"`               // 退款金额，单位元
	RefundRequestNo string  `json:"refund_request_no"`           // 商户退款请求号，同一订单退款不可重复
}

// HmPayTradeRefundResp 订单退款 trade.refund 业务响应参数
type HmPayTradeRefundResp struct {
	SubCode           string          `json:"sub_code"`                     // 业务返回码
	SubMsg            string          `json:"sub_msg"`                      // 业务返回信息
	RefundAmount      float64         `json:"refund_amount"`                // 退款金额
	OutOrderNo        string          `json:"out_order_no"`                 // 商户订单号
	PlatTrxNo         string          `json:"plat_trx_no"`                  // 平台交易流水号
	BankOrderNo       string          `json:"bank_order_no"`                // 银行订单号
	BankTrxNo         string          `json:"bank_trx_no"`                  // 银行流水号
	PayWayCode        string          `json:"pay_way_code"`                 // 支付方式
	BuyerID           string          `json:"buyer_id"`                     // 买家ID
	RefundRequestNo   string          `json:"refund_request_no"`            // 商户退款请求号
	RefundPlatTrxNo   string          `json:"refund_plat_trx_no"`           // 退款平台流水号
	RefundBankOrderNo string          `json:"refund_bank_order_no"`         // 退款银行订单号
	RefundBankTrxNo   string          `json:"refund_bank_trx_no,omitempty"` // 退款银行流水号（可选）
	ReqReserved       string          `json:"req_reserved,omitempty"`       // 自定义字段（可选）
	DiscountDetail    *DiscountDetail `json:"discount_detail,omitempty"`    // 优惠详情（可选）
}

// DiscountDetail 示例优惠详情结构体（根据业务自行扩展）
type DiscountDetail struct {
	// 可根据具体业务定义字段结构
	DiscountType   string  `json:"discount_type,omitempty"`   // 示例：优惠类型
	DiscountAmount float64 `json:"discount_amount,omitempty"` // 示例：优惠金额
}

type HmPayUnifiedOrderPayData struct {
	TimeStamp string `json:"timeStamp"`
	Package   string `json:"package"`
	PaySign   string `json:"paySign"`
	AppId     string `json:"appId"`
	SignType  string `json:"signType"`
	NonceStr  string `json:"nonceStr"`
}

type HmPayUnifiedOrderDetail struct {
	BankOrderNo string `json:"bank_order_no"`
	BankTrxNo   string `json:"bank_trx_no"`
	BankWay     string `json:"bank_way"`
	OutOrderNo  string `json:"out_order_no"`
	PayData     string `json:"pay_data"`
	PlatTrxNo   string `json:"plat_trx_no"`
	PrepayId    string `json:"prepay_id"`
	SubCode     string `json:"sub_code"`
	SubMsg      string `json:"sub_msg"`
}

type HmPayUnifiedOrderRsp struct {
	Code string `json:"code"`
	Msg  string `json:"msg"`
	Data string `json:"data"`
	Sign string `json:"sign"`
}

func ParsePrivateKeyDeovo(storeId uint32) (*rsa.PrivateKey, error) {
	storeKey := getStoreKeyConfig(storeId)
	privateKey, err := os.ReadFile(storeKey.FP)
	if err != nil {
		logger.Errorf("read file err:", err)
		return nil, err
	}

	block, _ := pem.Decode([]byte(privateKey))
	if block == nil {
		return nil, errors.New("私钥信息错误！")
	}
	//priKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	priKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
	if err != nil {
		return nil, err
	}
	if priKey == nil {
		return nil, errors.New("pri key is nil")
	}
	return priKey.(*rsa.PrivateKey), nil
}

func Sha1withRsaDeovo(storeId uint32, signContent string) (string, error) {
	hash := crypto.SHA1
	shaNew := hash.New()
	shaNew.Write([]byte(signContent))
	hashed := shaNew.Sum(nil)
	priKey, err := ParsePrivateKeyDeovo(storeId)
	if err != nil {
		logger.Errorf("parse err:", err)
		return "", err
	}

	signature, err := rsa.SignPKCS1v15(rand.Reader, priKey, hash, hashed)
	if err != nil {
		logger.Errorf("sign err:", err)
		return "", err
	}
	return b64.StdEncoding.EncodeToString(signature), nil
}

func GenHmPaySignDeovo(storeId uint32, m map[string]string) (string, error) {
	delete(m, "sign")
	var signData []string
	for k, v := range m {
		if k == "openid" {
			fmt.Println(k, ":", v)
		}
		if v != "" && v != "0" {
			signData = append(signData, fmt.Sprintf("%s=%s", k, v))
		}
	}
	//signDataJson, _ := json.MarshalIndent(&signData, "", "    ")
	//fmt.Println("signDataJson1", string(signDataJson))

	sort.Strings(signData)

	//signDataJson2, _ := json.MarshalIndent(&signData, "", "    ")
	//fmt.Println("signDataJson2", string(signDataJson2))

	signStr := strings.Join(signData, "&")
	//signStr = signStr + "&key=" + payKey
	//logger.Info("签字符串1:", logger.Field("signStr", signStr))
	fmt.Println("签字符串1:", signStr)

	signature, err := Sha1withRsaDeovo(storeId, signStr)
	if err != nil {
		logger.Errorf("signature err:", err)
		return "", err
	}
	return signature, nil
}

func ParsePrivateKey() (*rsa.PrivateKey, error) {
	//fp := "/Users/max/Documents/code/deovo/mh_goadmin_server/config/hm_pay/private_key.pem"
	fp := "./config/hm_pay/private_key.pem"
	privateKey, err := os.ReadFile(fp)
	if err != nil {
		logger.Errorf("read file err:", err)
		return nil, err
	}

	block, _ := pem.Decode([]byte(privateKey))
	if block == nil {
		return nil, errors.New("私钥信息错误！")
	}
	//priKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	priKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
	if err != nil {
		return nil, err
	}
	if priKey == nil {
		return nil, errors.New("pri key is nil")
	}
	return priKey.(*rsa.PrivateKey), nil
}

func Sha1withRsa(signContent string) (string, error) {
	hash := crypto.SHA1
	shaNew := hash.New()
	shaNew.Write([]byte(signContent))
	hashed := shaNew.Sum(nil)
	priKey, err := ParsePrivateKey()
	if err != nil {
		logger.Errorf("parse err:", err)
		return "", err
	}

	signature, err := rsa.SignPKCS1v15(rand.Reader, priKey, hash, hashed)
	if err != nil {
		logger.Errorf("sign err:", err)
		return "", err
	}
	return b64.StdEncoding.EncodeToString(signature), nil
}

func GenHmPaySign(m map[string]string) (string, error) {
	delete(m, "sign")
	var signData []string
	for k, v := range m {
		if k == "openid" {
			fmt.Println(k, ":", v)
		}
		if v != "" && v != "0" {
			signData = append(signData, fmt.Sprintf("%s=%s", k, v))
		}
	}
	//signDataJson, _ := json.MarshalIndent(&signData, "", "    ")
	//fmt.Println("signDataJson1", string(signDataJson))

	sort.Strings(signData)

	//signDataJson2, _ := json.MarshalIndent(&signData, "", "    ")
	//fmt.Println("signDataJson2", string(signDataJson2))

	signStr := strings.Join(signData, "&")
	//signStr = signStr + "&key=" + payKey
	//logger.Info("签字符串1:", logger.Field("signStr", signStr))
	fmt.Println("签字符串1:", signStr)

	signature, err := Sha1withRsa(signStr)
	if err != nil {
		logger.Errorf("signature err:", err)
		return "", err
	}
	return signature, nil
}

func FormatPrivateKey(privateKey string) string {
	//privateKey = strings.Trim(privateKey, "\n")
	if !strings.HasPrefix(privateKey, PemBegin) {
		privateKey = PemBegin + privateKey
	}
	if !strings.HasSuffix(privateKey, PemEnd) {
		privateKey = privateKey + PemEnd
	}
	return privateKey
}

func HmPayUnifiedOrder(r HmJsPayUnifiedOrderReq) (HmPayUnifiedOrderRsp, error) {
	var hmPayUnifiedOrderRsp HmPayUnifiedOrderRsp

	data, err := json.Marshal(r)
	if err != nil {
		logger.Error("HmPayUnifiedOrder err:", logger.Field("err", err))
		return hmPayUnifiedOrderRsp, err
	}

	fmt.Println("data json:", string(data))
	client := http.Client{}
	req, err := http.NewRequest("POST", HmPayApiUrl, bytes.NewBuffer(data))
	if err != nil {
		logger.Error("HmPayUnifiedOrder err:", logger.Field("err", err))
		return hmPayUnifiedOrderRsp, err
	}
	req.Header.Set("Content-Type", "application/json; charset=utf-8")
	//req.Header.Set("Content-Type", "application/json")

	resp, err := client.Do(req)
	if err != nil {
		logger.Error("HmPayUnifiedOrder err:", logger.Field("err", err))
		return hmPayUnifiedOrderRsp, err
	}

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		logger.Error("HmPayUnifiedOrder err:", logger.Field("err", err))
		return hmPayUnifiedOrderRsp, err
	}
	fmt.Println("body:", string(body))

	defer resp.Body.Close()

	err = json.Unmarshal(body, &hmPayUnifiedOrderRsp)
	if err != nil {
		logger.Error("hmPayUnifiedOrderRsp err:", logger.Field("err", err))
		return hmPayUnifiedOrderRsp, err
	}
	if hmPayUnifiedOrderRsp.Code != "200" {
		return hmPayUnifiedOrderRsp, errors.New(hmPayUnifiedOrderRsp.Msg)
	}

	return hmPayUnifiedOrderRsp, nil
}

func HmVerifySha1RsaDeovo(storeId uint32, signContent, signBase string) error {
	//fp := "/Users/li/mh/mh_server/pack/configs/hm_pay/public_key.pme"
	//publicKeyString, err := ioutil.ReadFile(fp)
	//if err != nil {
	//	fmt.Println("read file err:", err)
	//	return err
	//}

	storeKey := getStoreKeyConfig(storeId)
	block, _ := pem.Decode([]byte(FormatPrivateKey(storeKey.PubKey)))
	if block == nil {
		fmt.Println("decode block is nil")
		return errors.New("decode block is nil")
	}
	publicKey, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		fmt.Println("public key  err:", err)
		return err
	}

	if publicKey == nil {
		fmt.Println("public key  nil:")
		return err
	}
	hash := crypto.SHA1
	shaNew := hash.New()
	shaNew.Write([]byte(signContent))
	hashed := shaNew.Sum(nil)

	sign, err := b64.StdEncoding.DecodeString(signBase)
	if err != nil {
		fmt.Println("sign decode err:", err)
		return err
	}

	err = rsa.VerifyPKCS1v15(publicKey.(*rsa.PublicKey), hash, hashed, sign)
	if err != nil {
		fmt.Println("verify err:", err)
		return err
	}
	//logger.Error("验签成功")
	fmt.Println("验签成功")
	return nil
}

func HmVerifySha1Rsa(signContent, signBase string) error {
	//fp := "/Users/li/mh/mh_server/pack/configs/hm_pay/public_key.pme"
	//publicKeyString, err := ioutil.ReadFile(fp)
	//if err != nil {
	//	fmt.Println("read file err:", err)
	//	return err
	//}

	block, _ := pem.Decode([]byte(FormatPrivateKey(HmPubKey)))
	if block == nil {
		fmt.Println("decode block is nil")
		return errors.New("decode block is nil")
	}
	publicKey, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		fmt.Println("public key  err:", err)
		return err
	}

	if publicKey == nil {
		fmt.Println("public key  nil:")
		return err
	}
	hash := crypto.SHA1
	shaNew := hash.New()
	shaNew.Write([]byte(signContent))
	hashed := shaNew.Sum(nil)

	sign, err := b64.StdEncoding.DecodeString(signBase)
	if err != nil {
		fmt.Println("sign decode err:", err)
		return err
	}

	err = rsa.VerifyPKCS1v15(publicKey.(*rsa.PublicKey), hash, hashed, sign)
	if err != nil {
		fmt.Println("verify err:", err)
		return err
	}
	//logger.Error("验签成功")
	fmt.Println("验签成功")
	return nil
}

func ToSignContent(s interface{}) (string, error) {
	m, err := struct2Map(s)
	if err != nil {
		logger.Error("ToSignContent err:", logger.Field("err", err))
		return "", err
	}

	delete(m, "sign")
	var signData []string
	for k, v := range m {
		if k == "openid" {
			fmt.Println(k, ":", v)
		}
		if v != "" && v != "0" {
			signData = append(signData, fmt.Sprintf("%s=%s", k, v))
		}
	}

	sort.Strings(signData)

	//signDataJson2, _ := json.MarshalIndent(&signData, "", "    ")
	//fmt.Println("signDataJson2", string(signDataJson2))

	signStr := strings.Join(signData, "&")

	return signStr, nil
}

type StoreKeyConfig struct {
	AppID  string
	FP     string
	PubKey string
}

func getStoreKeyConfig(storeId uint32) StoreKeyConfig {
	var config StoreKeyConfig

	switch storeId {
	case 19, 23, 27, 28: // 汕头万象城, 海雅缤纷城, 布吉万象汇, 大运天地
		config = StoreKeyConfig{
			AppID:  HmPayMerchantIdSwitchPub,
			FP:     HmPubKeySwitchPubFp,
			PubKey: HmPubKeySwitchPub,
		}
	case 13: // 万象天地
		config = StoreKeyConfig{
			AppID:  HmPayMerchantIdSwitch,
			FP:     HmPubKeySwitchFp,
			PubKey: HmPubKeySwitch,
		}
	case 29: // JBL哈曼店
		now := time.Now()
		start := time.Date(now.Year(), now.Month(), now.Day(), 16, 30, 0, 0, now.Location())
		end := time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, now.Location())
		if now.After(start) && now.Before(end) {
			config = StoreKeyConfig{
				AppID:  HmPayMerchantIdJBLPub,
				FP:     HmPubKeyJBLPubFp,
				PubKey: HmPubKeyJBLPub,
			}
		} else {
			config = StoreKeyConfig{
				AppID:  HmPayMerchantIdJBL,
				FP:     HmPubKeyJBLFp,
				PubKey: HmPubKeyJBL,
			}
		}
	case 100001: // 明慧帐户-小程序商城
		config = StoreKeyConfig{
			AppID:  HmPayMerchantId,
			FP:     HmPubKeyFp,
			PubKey: HmPubKey,
		}
	}

	return config
}

// HmJsPayBToCOrder 河马刷卡支付（B扫C）
func HmJsPayBToCOrder(storeId uint32, orderId string, totalFee float64, authCode, notifyUrl string) (*HmPayBToCOrderDetail, error) {
	now := time.Now().Local()
	strTime := fmt.Sprintf("%04d%02d%02d%02d%02d%02d", now.Year(), now.Month(), now.Day(), now.Hour(),
		now.Minute(), now.Second())
	nonce := GenRandStr(NonceStringLength)

	//if notifyUrl == "" {
	//	logger.Error("NotifyUrl is null")
	//	return nil, errors.New("NotifyUrl is null")
	//}

	storeKey := getStoreKeyConfig(storeId)

	unifiedOrderReq := HmJsPayUnifiedOrderReq{}
	publicPara := HmPayPublicPara{
		AppId: storeKey.AppID,
		//SubAppId:  HmWxSubMerchantId,
		Method: "trade.pay",
		//Charset:   "UTF-8",
		SignType:  "RSA",
		Sign:      "",
		Timestamp: now.Format(TimeFormat),
		Nonce:     nonce,
		//Nonce: fmt.Sprintf("%d", time.Now().UnixNano()),
		//Version:   "1.0.0",
		//Format:    "JSON",
	}

	biz := HmPayBToCBizContent{
		AuthCode:    authCode,
		CreateIp:    clientIp,
		CreateTime:  strTime,
		PayWay:      "AUTO",
		TotalAmount: totalFee,
		OutOrderNo:  orderId,
		Body:        "门店消费",
		StoreId:     "100001",
		TerminalId:  fmt.Sprintf("%d", storeId),
		NotifyUrl:   notifyUrl,
	}

	if config.ApplicationConfig.Mode == "dev" {
		biz.CreateIp = clientIpDev
		biz.TerminalId = "test999" // 测试终端
	}

	unifiedOrderReq.HmPayPublicPara = publicPara

	bizString, err := json.Marshal(&biz)
	if err != nil {
		logger.Error("marshal biz err:", logger.Field("err", err))
		return nil, err
	}
	unifiedOrderReq.HmPayPublicPara.BizContent = string(bizString)
	m, err := struct2Map(unifiedOrderReq)
	if err != nil {
		logger.Error("HmJsPayUnifiedOrder struct2Map err:", logger.Field("err", err))
		return nil, err
	}

	sign, err := GenHmPaySignDeovo(storeId, m)
	if err != nil {
		logger.Error("HmJsPayUnifiedOrder GenHmPaySign err:", logger.Field("err", err))
		return nil, err
	}
	unifiedOrderReq.Sign = sign

	unifiedOrderResp, err := HmPayUnifiedOrder(unifiedOrderReq)
	if err != nil {
		logger.Errorf("WxUnifiedOrder unified order error %#v", err)
		return nil, err
	}

	signContent, err := ToSignContent(unifiedOrderResp)
	if err != nil {
		logger.Errorf("ToSignContent err:", err)
		return nil, err
	}

	err = HmVerifySha1RsaDeovo(storeId, signContent, unifiedOrderResp.Sign)
	if err != nil {
		logger.Errorf("HmVerifySha1Rsa err:", err)
		return nil, err
	}

	//fmt.Println("unifiedOrderResp:", unifiedOrderResp.Data)
	var hmPayDetail HmPayBToCOrderDetail
	err = json.Unmarshal([]byte(unifiedOrderResp.Data), &hmPayDetail)
	if err != nil {
		logger.Errorf("hm pay unified order pay data unmarshal  error %#v", err)
		return nil, err
	}
	logger.Info("刷卡付响应参数：:", logger.Field("HmPayBToCOrderDetail", hmPayDetail))

	return &hmPayDetail, nil
}

// HmQueryOrder 订单查询
func HmQueryOrder(orderId string, storeId uint32) (*HmPayTradeQueryResp, error) {
	now := time.Now().Local()
	nonce := GenRandStr(NonceStringLength)

	storeKey := getStoreKeyConfig(storeId)
	unifiedOrderReq := HmJsPayUnifiedOrderReq{}
	publicPara := HmPayPublicPara{
		AppId:     storeKey.AppID,
		Method:    "trade.query",
		SignType:  "RSA",
		Sign:      "",
		Timestamp: now.Format(TimeFormat),
		Nonce:     nonce,
	}

	biz := HmPayTradeQueryContent{
		OutOrderNo: orderId,
	}
	unifiedOrderReq.HmPayPublicPara = publicPara

	bizString, err := json.Marshal(&biz)
	if err != nil {
		logger.Error("marshal biz err:", logger.Field("err", err))
		return nil, err
	}
	unifiedOrderReq.HmPayPublicPara.BizContent = string(bizString)
	m, err := struct2Map(unifiedOrderReq)
	if err != nil {
		logger.Error("HmJsPayUnifiedOrder struct2Map err:", logger.Field("err", err))
		return nil, err
	}

	sign, err := GenHmPaySignDeovo(storeId, m)
	if err != nil {
		logger.Error("HmJsPayUnifiedOrder GenHmPaySign err:", logger.Field("err", err))
		return nil, err
	}
	unifiedOrderReq.Sign = sign

	unifiedOrderResp, err := HmPayUnifiedOrder(unifiedOrderReq)
	if err != nil {
		logger.Errorf("WxUnifiedOrder unified order error %#v", err)
		return nil, err
	}

	signContent, err := ToSignContent(unifiedOrderResp)
	if err != nil {
		logger.Errorf("ToSignContent err:", err)
		return nil, err
	}
	err = HmVerifySha1RsaDeovo(storeId, signContent, unifiedOrderResp.Sign)
	if err != nil {
		logger.Errorf("HmVerifySha1Rsa err:", err)
		return nil, err
	}
	fmt.Println("Resp Data:", unifiedOrderResp.Data)

	var hmPayDetail HmPayTradeQueryResp
	err = json.Unmarshal([]byte(unifiedOrderResp.Data), &hmPayDetail)
	if err != nil {
		logger.Errorf("hm pay unified order pay data unmarshal  error %#v", err)
		return nil, err
	}

	logger.Info("订单查询响应参数：:", logger.Field("HmPayTradeQueryResp", hmPayDetail))

	return &hmPayDetail, nil
}

// HmCancelOrder 订单撤销
func HmCancelOrder(orderId string, storeId uint32) (*HmPayTradeCancelResp, error) {
	now := time.Now().Local()
	nonce := GenRandStr(NonceStringLength)

	storeKey := getStoreKeyConfig(storeId)
	unifiedOrderReq := HmJsPayUnifiedOrderReq{}
	publicPara := HmPayPublicPara{
		AppId:     storeKey.AppID,
		Method:    "trade.cancel",
		SignType:  "RSA",
		Sign:      "",
		Timestamp: now.Format(TimeFormat),
		Nonce:     nonce,
	}

	biz := HmPayTradeCancelContent{
		OutOrderNo: orderId,
	}
	unifiedOrderReq.HmPayPublicPara = publicPara

	bizString, err := json.Marshal(&biz)
	if err != nil {
		logger.Error("marshal biz err:", logger.Field("err", err))
		return nil, err
	}
	unifiedOrderReq.HmPayPublicPara.BizContent = string(bizString)
	m, err := struct2Map(unifiedOrderReq)
	if err != nil {
		logger.Error("HmJsPayUnifiedOrder struct2Map err:", logger.Field("err", err))
		return nil, err
	}

	sign, err := GenHmPaySignDeovo(storeId, m)
	if err != nil {
		logger.Error("HmJsPayUnifiedOrder GenHmPaySign err:", logger.Field("err", err))
		return nil, err
	}
	unifiedOrderReq.Sign = sign

	unifiedOrderResp, err := HmPayUnifiedOrder(unifiedOrderReq)
	if err != nil {
		logger.Errorf("WxUnifiedOrder unified order error %#v", err)
		return nil, err
	}

	signContent, err := ToSignContent(unifiedOrderResp)
	if err != nil {
		logger.Errorf("ToSignContent err:", err)
		return nil, err
	}
	err = HmVerifySha1RsaDeovo(storeId, signContent, unifiedOrderResp.Sign)
	if err != nil {
		logger.Errorf("HmVerifySha1Rsa err:", err)
		return nil, err
	}
	fmt.Println("Resp Data:", unifiedOrderResp.Data)

	var hmPayDetail HmPayTradeCancelResp
	err = json.Unmarshal([]byte(unifiedOrderResp.Data), &hmPayDetail)
	if err != nil {
		logger.Errorf("hm pay unified order pay data unmarshal  error %#v", err)
		return nil, err
	}
	fmt.Println("hmPayDetail:", hmPayDetail)

	return &hmPayDetail, nil
}

// HmRefundOrder 订单退款
func HmRefundOrder(req HmPayTradeRefundContent, storeId uint32) (*HmPayTradeRefundResp, error) {
	now := time.Now().Local()
	nonce := GenRandStr(NonceStringLength)

	storeKey := getStoreKeyConfig(storeId)
	unifiedOrderReq := HmJsPayUnifiedOrderReq{}
	publicPara := HmPayPublicPara{
		AppId:     storeKey.AppID,
		Method:    "trade.refund",
		SignType:  "RSA",
		Sign:      "",
		Timestamp: now.Format(TimeFormat),
		Nonce:     nonce,
	}

	biz := HmPayTradeRefundContent{
		OutOrderNo:      req.OutOrderNo,
		PlatTrxNo:       req.PlatTrxNo,
		RefundAmount:    req.RefundAmount,
		RefundRequestNo: req.RefundRequestNo,
	}
	unifiedOrderReq.HmPayPublicPara = publicPara

	bizString, err := json.Marshal(&biz)
	if err != nil {
		logger.Error("marshal biz err:", logger.Field("err", err))
		return nil, err
	}
	unifiedOrderReq.HmPayPublicPara.BizContent = string(bizString)
	m, err := struct2Map(unifiedOrderReq)
	if err != nil {
		logger.Error("HmJsPayUnifiedOrder struct2Map err:", logger.Field("err", err))
		return nil, err
	}

	sign, err := GenHmPaySignDeovo(storeId, m)
	if err != nil {
		logger.Error("HmJsPayUnifiedOrder GenHmPaySign err:", logger.Field("err", err))
		return nil, err
	}
	unifiedOrderReq.Sign = sign

	unifiedOrderResp, err := HmPayUnifiedOrder(unifiedOrderReq)
	if err != nil {
		logger.Errorf("WxUnifiedOrder unified order error %#v", err)
		return nil, err
	}

	signContent, err := ToSignContent(unifiedOrderResp)
	if err != nil {
		logger.Errorf("ToSignContent err:", err)
		return nil, err
	}
	err = HmVerifySha1RsaDeovo(storeId, signContent, unifiedOrderResp.Sign)
	if err != nil {
		logger.Errorf("HmVerifySha1Rsa err:", err)
		return nil, err
	}
	fmt.Println("Resp Data:", unifiedOrderResp.Data)

	var hmPayDetail HmPayTradeRefundResp
	err = json.Unmarshal([]byte(unifiedOrderResp.Data), &hmPayDetail)
	if err != nil {
		logger.Errorf("hm pay unified order pay data unmarshal  error %#v", err)
		return nil, err
	}
	fmt.Println("hmPayDetail:", hmPayDetail)

	return &hmPayDetail, nil
}
