484 lines
15 KiB
Go
484 lines
15 KiB
Go
|
package pay
|
|||
|
|
|||
|
import (
|
|||
|
"context"
|
|||
|
"crypto/md5"
|
|||
|
"crypto/tls"
|
|||
|
"encoding/json"
|
|||
|
"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"
|
|||
|
//"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"
|
|||
|
)
|
|||
|
|
|||
|
const (
|
|||
|
mchID string = "1609877389" // 商户号
|
|||
|
mchCertificateSerialNumber string = "7540301D8FD52CCF7D6267DCF7CD2BC0AB467EFF" // 商户证书序列号
|
|||
|
mchAPIv3Key string = "DeovoMingHuiRengTianTang45675123" // 商户APIv3密钥
|
|||
|
)
|
|||
|
|
|||
|
//var (
|
|||
|
// mchID string = "1609877389" // 商户号
|
|||
|
// mchCertificateSerialNumber string = "7540301D8FD52CCF7D6267DCF7CD2BC0AB467EFF" // 商户证书序列号
|
|||
|
// mchAPIv3Key string = "DeovoMingHuiRengTianTang45675123" // 商户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
|
|||
|
}
|
|||
|
|
|||
|
//给用户打款
|
|||
|
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)
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
|
|||
|
sign, err := GenWechatPaySign(m, WxAppMchSecret)
|
|||
|
if err != nil {
|
|||
|
logger.Error(err)
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
req.Sign = strings.ToUpper(sign)
|
|||
|
|
|||
|
payload, err := xml.Marshal(&req)
|
|||
|
if err != nil {
|
|||
|
logger.Error(err)
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
|
|||
|
request, err := newPostRequest(WxTransferUrl, string(payload))
|
|||
|
if err != nil {
|
|||
|
logger.Error(err)
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
defer request.Body.Close()
|
|||
|
logger.Info("证书路径:", WxRootCaFile)
|
|||
|
logger.Info("证书路径:", WxKeyFile)
|
|||
|
client, err := newHttpClient(WxRootCaFile, WxKeyFile)
|
|||
|
if err != nil {
|
|||
|
logger.Error(err)
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
|
|||
|
resp, err := client.Do(request)
|
|||
|
defer resp.Body.Close()
|
|||
|
|
|||
|
body, err := ioutil.ReadAll(resp.Body)
|
|||
|
if err != nil {
|
|||
|
logger.Error(err)
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
//logger.Info("Transfer resp = ", string(body))
|
|||
|
logger.Info("Transfer resp = ", string(body))
|
|||
|
err = xml.Unmarshal(body, &wxResp)
|
|||
|
if err != nil {
|
|||
|
logger.Error(err)
|
|||
|
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 :", 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:", 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) error {
|
|||
|
var (
|
|||
|
mchID string = "1609877389" // 商户号
|
|||
|
mchCertificateSerialNumber string = "7540301D8FD52CCF7D6267DCF7CD2BC0AB467EFF" // 商户证书序列号
|
|||
|
mchAPIv3Key string = "DeovoMingHuiRengTianTang45675123" // 商户APIv3密钥
|
|||
|
)
|
|||
|
|
|||
|
// WxKeyFile = "./config/merchant/apiclient_key.pem"
|
|||
|
// mchPrivateKey, err := wechatpayutils.LoadPrivateKeyWithPath("/Users/li/mh/mh_admin_server/app/admin/apis/pay/merchant/apiclient_key.pem")
|
|||
|
|
|||
|
privatePath := "./config/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(mchID, mchCertificateSerialNumber, mchPrivateKey, mchAPIv3Key),
|
|||
|
}
|
|||
|
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 {
|
|||
|
// 处理错误
|
|||
|
log.Printf("call Create err:%s", err)
|
|||
|
} else {
|
|||
|
// 处理返回结果
|
|||
|
log.Printf("status=%d resp=%s", result.Response.StatusCode, resp)
|
|||
|
}
|
|||
|
|
|||
|
return nil
|
|||
|
}
|