|
package wechat
|
|
|
|
import (
|
|
"context"
|
|
"crypto/rsa"
|
|
"crypto/x509"
|
|
"errors"
|
|
"git.tetele.net/tgo/helper"
|
|
"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/utils"
|
|
"io/ioutil"
|
|
"log"
|
|
)
|
|
|
|
/**
|
|
* 商户订单号,退款单号,总金额,退款金额,微信商户id,微信商户平台API私钥,平台证书,商户平台证书序列号,商品名,商品id,退款原因,回调地址
|
|
*/
|
|
func CreateRefund(order_sn, out_refund_no, total_amount, refund_amount, wx_mp_mch_id, wx_mch_apiclient_key,
|
|
wx_pay_cert, mch_serial_no, title, uuid, reason, notify_url string) (map[string]interface{}, error) {
|
|
total := helper.ToInt64(helper.FloatMul(total_amount, 100)) //总金额
|
|
refund := helper.ToInt64(helper.FloatMul(refund_amount, 100)) //退款金额
|
|
|
|
log.Println("refund", order_sn, out_refund_no, refund, total, notify_url)
|
|
|
|
var (
|
|
ctx context.Context = context.Background()
|
|
client *core.Client
|
|
)
|
|
|
|
privateKey, err := utils.LoadPrivateKey(wx_mch_apiclient_key)
|
|
if err != nil {
|
|
log.Println("商户私钥有误:", err)
|
|
return map[string]interface{}{}, errors.New("商户私钥有误")
|
|
}
|
|
wechatPayCertificate, err := utils.LoadCertificate(wx_pay_cert)
|
|
if err != nil {
|
|
log.Println("平台证书有误:", err)
|
|
return map[string]interface{}{}, errors.New("商户平台证书有误")
|
|
}
|
|
client, err = CreateClient(ctx, wechatPayCertificate, privateKey, wx_mp_mch_id, mch_serial_no)
|
|
if err != nil {
|
|
return map[string]interface{}{}, errors.New("请检查支付参数配置")
|
|
}
|
|
|
|
// now := time.Now()
|
|
|
|
svc := refunddomestic.RefundsApiService{Client: client}
|
|
_, result, err := svc.Create(ctx,
|
|
refunddomestic.CreateRequest{
|
|
Amount: &refunddomestic.AmountReq{
|
|
Currency: core.String("CNY"),
|
|
// From: []refunddomestic.FundsFromItem{refunddomestic.FundsFromItem{
|
|
// Account: refunddomestic.ACCOUNT_AVAILABLE.Ptr(),
|
|
// Amount: core.Int64(444),
|
|
// }},
|
|
Refund: core.Int64(refund),
|
|
Total: core.Int64(total),
|
|
},
|
|
// FundsAccount: refunddomestic.REQFUNDSACCOUNT_AVAILABLE.Ptr(),
|
|
GoodsDetail: []refunddomestic.GoodsDetail{refunddomestic.GoodsDetail{
|
|
GoodsName: core.String(title),
|
|
MerchantGoodsId: core.String(uuid),
|
|
RefundAmount: core.Int64(refund),
|
|
RefundQuantity: core.Int64(1),
|
|
UnitPrice: core.Int64(refund),
|
|
// WechatpayGoodsId: core.String("1001"),
|
|
}},
|
|
NotifyUrl: core.String(notify_url),
|
|
OutRefundNo: core.String(out_refund_no),
|
|
OutTradeNo: core.String(order_sn),
|
|
Reason: core.String(reason),
|
|
// SubMchid: core.String("1900000109"),
|
|
// TransactionId: core.String("1217752501201407033233368018"),
|
|
},
|
|
)
|
|
|
|
res := map[string]interface{}{}
|
|
log.Println("Response:", result.Response)
|
|
log.Println("Response Body:", result.Response.Body)
|
|
if err != nil {
|
|
response_body := map[string]interface{}{}
|
|
body, _ := ioutil.ReadAll(result.Response.Body)
|
|
err_body := json.Unmarshal(body, &response_body)
|
|
if err_body != nil {
|
|
res["code"] = "RESPONSE_BODY_ERROR"
|
|
res["message"] = "退款回调参数异常"
|
|
return res, err_body
|
|
}
|
|
log.Println("response_body:", response_body)
|
|
res["code"] = response_body["code"]
|
|
res["message"] = response_body["message"]
|
|
return res, errors.New(helper.ToStr(response_body["message"]))
|
|
}
|
|
res["code"] = "success"
|
|
res["message"] = "退款成功"
|
|
return res, nil
|
|
}
|
|
func CreateClient(ctx context.Context, wechatPayCertificate *x509.Certificate, privateKey *rsa.PrivateKey, mchID, mchSerialNo string) (*core.Client, error) {
|
|
|
|
var client *core.Client
|
|
var err error
|
|
|
|
if wechatPayCertificate != nil {
|
|
|
|
client, err = core.NewClient(
|
|
ctx, option.WithMerchantCredential(mchID, mchSerialNo, privateKey),
|
|
option.WithWechatPayCertificate([]*x509.Certificate{wechatPayCertificate}),
|
|
)
|
|
if err != nil {
|
|
log.Println("创建 Client 失败:", err)
|
|
return nil, err
|
|
}
|
|
} else {
|
|
client, err = core.NewClient(
|
|
ctx, option.WithMerchantCredential(mchID, mchSerialNo, privateKey), option.WithoutValidator(),
|
|
)
|
|
if err != nil {
|
|
log.Println("创建 Client 失败:", err)
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return client, nil
|
|
}
|