@ -0,0 +1,126 @@ | |||
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 | |||
} |
@ -0,0 +1,27 @@ | |||
package wechat | |||
import ( | |||
"github.com/kayon/iploc" | |||
"testing" | |||
) | |||
func Test_CreateRefund(t *testing.T) { | |||
wx_mch_apiclient_key := "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDsea/umgdNz68w\nBdISLMPg+5E5Od2EDblO0ifz60P92kyIIQgFMKnw7sawfYlQNMs7fTOKMUBFoSJH\nzUNdOXUxLTmvPg9Pnh2jBBDQkUqBCMvUSsk5WzqF2VTSAmESy2XnfbGrXz9Q4KhV\nsLwP9O0qFDCrxgqjhKStUew6wNBq03lPnyvOee7QQ3eBZYY2z98XXjHai4nH7Lwi\nzwfYN23P/1QjWcs7a+J53v9KXjlEofNQzoXKy0hJnkPySTF8J9V7vBkbNwRceDVD\ng/uCsZ+ZBYEqwVtu7TkBaFZS06/y8/9iGNyvVLTBOzyX5XTxMAjSctRKuHEkzTII\n4ikNGtxbAgMBAAECggEAG8ez3lDj+MUkLH0Sj6YIoN6M0e81UbUXBuZzYRlLVIAX\nq4pN2eY8oJw8ZTFqNyzsjyGHM33Tshpa35qChmoglVVdyHN+8vh9PNBWdVoMKZpx\n74+VkhJgjqbYaw9yffW9E/PVMm+vDX5G6EIp5an9TosuqI9MYqdLfTz5hnFuSo4x\ngZvJmQZ/NytYjUDUOKejHjMFcfb9oBJpMDD+cOpqbK8DI9t+a4WWFxgX25TsgtzY\n9Dwnx/H4gXoDBU5nayZ5aQ1EXwNcH6s+XbAYQUpneWyjdsmg5mCuIRf/DaC0amAx\ncyGU74YJA1/eapD+TJsrNmboMdXFBUVsdwGrlF1IMQKBgQD/bUiCdYKKMC5DKidB\nrT6YqJC3lDoSbAQw/vhOy6xP1zegJdX3irlFweKCEzhRTlStV7C/vBe7eylz303Q\nUS6T59piEtKLlSJNxiPTWH0Gr+KGdJJgXa/fZPL0OEEDE7ScDrbGtAPrKLCM+Nx1\nXHujy/g2i1hbKuD82wWFidcfwwKBgQDtAYSslD/43qSGngWom2UPCr7b5nlhk9Xh\nihztlrTV+txCE5KUx1dq2kuYU2sywDlDJN7+v0XW+YhQi7PVGI5eWwh4voR87x/4\nSKhHxhkKPG1EFSU/oX8rmWUvYArgYBNFBfC7EdxbjfBGZn6lJrpRwQN1MJivGJlB\nTS4NFXDfiQKBgQD+Iwd/9dcaEvIUlX5VlD+xuBW08eANsDdDYIxCKdeZ4LJRvxNy\npi3MwCnT7bec/ei2R4duXYDnYpVN2qIbYIqNUqQv7DZb9tgYtcmzYFmVK66gxJ9X\nDiAMju5EGyxkGVkb5G/qp/U2JlfzCzCd/JRv1mNyMZaJrtIIAwstYIYP7QKBgD2p\npnYsQBSlAJNRq9E5VOq79fpKlYwQpZX/lBUwn64IjaPXacyxrInNb9ua4Iocvwk8\nH5SR+T68P34NSuWHdQsRjjuz/c5vfJbheH7sCHnETP1orv9GKksSpuPTjiDgfkL4\nD7DsLbPYUwpOAmc/kzxQBnFICoGL2dvGk9Otn2dZAoGBAOsn4AKGN/8PcFAJ2CgA\nZiqlninYOqWZl6dYdLRnhZ8sFF9MlOFPH+0OnRgNWihuF1Mbjjs1vuIP/2bgWAEw\nBr5hb+CyVD17FKICcb9Aa+hZarppRwuPkdNNcrOAOtCcHBV1k3Syp853OyUUqO8a\nxM/YXk8qkTIx0EdnYgemHeWh\n-----END PRIVATE KEY-----" | |||
wx_pay_cert := "-----BEGIN CERTIFICATE-----\nMIID3DCCAsSgAwIBAgIUWlZytNdS/jkalg7CE2RiKZk0qa8wDQYJKoZIhvcNAQEL\nBQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT\nFFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg\nQ0EwHhcNMjAwODA0MDgwMzI0WhcNMjUwODAzMDgwMzI0WjBuMRgwFgYDVQQDDA9U\nZW5wYXkuY29tIHNpZ24xEzARBgNVBAoMClRlbnBheS5jb20xHTAbBgNVBAsMFFRl\nbnBheS5jb20gQ0EgQ2VudGVyMQswCQYDVQQGDAJDTjERMA8GA1UEBwwIU2hlblpo\nZW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDU68UowJdEQlwqB1ID\nTpnfmsn6hR9xeTOTMt4db6tuAtExA5yNRU9T8ilBeEPIqjAPxHq/V6mDxwhw7gur\nSbqS80YhaHqqwFTu4lfktlHa3/xi3Itty9+70e75evlem+OY2OQEjpWtKnKjq7Op\nMrHpihkpxXbYxvTQe8yR99cSm3Pa9SR5FXL3rqs3f/M1LBw5faUBG/7ak+LZvqmD\nokdJVXk5VJg3TPtt/QOAwC4QeDCFt1uzPqs8LJWuLbQczHd0hzUvDye+9tIQ5eDM\nDoyME0YTZfspnn4WD3fQSCnf2oL8t2E1Che9w0lydXpNkYEgMgTLuX344jHSn6DY\nDNLVAgMBAAGjgYEwfzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIE8DBlBgNVHR8EXjBc\nMFqgWKBWhlRodHRwOi8vZXZjYS5pdHJ1cy5jb20uY24vcHVibGljL2l0cnVzY3Js\nP0NBPTFCRDQyMjBFNTBEQkMwNEIwNkFEMzk3NTQ5ODQ2QzAxQzNFOEVCRDIwDQYJ\nKoZIhvcNAQELBQADggEBAClIek1KQAFhAIoP1UKXb/zFOGdWVuBD4vg/3aT33MlW\nsXmCH+oB6QyuY0tqIaQ5XfnvUgFFuTk+kMQuq2Tayj6XNozu1pteVtQ//3u2V9DF\nGXNxiT588EeN1od9qT+zhLH6nuptw++mlxBorQQ3BJvgX3NIOgFU/ajCiSkGAnpj\nD4QcHWzsM6kwpK6JUuPDRq3E7O/1cCJkt6a20JQj+fbYJ0By28PgdvaphuK8lW3e\nuSlkSNLP/a1F7sp5xHMW4a/E+/OF9D4ETHfoQhVYwOTHlxpnXPLApQtj9zcwr64/\nU9DP6BALDin+8uBDDkxsF29VyCYZ/l6LdsnYD+ihbSo=\n-----END CERTIFICATE-----" | |||
ret, err := CreateRefund("6006167143914016978", "111223", "0.01", "0.01", "1298704001", wx_mch_apiclient_key, wx_pay_cert, "4642B326DDDDEAC74C677C163FB82BC95DCE43C0", "中餐", "122331", "yuanyin", "https://ttl-mini.tetele.net/admin/user/user/ttt_refund") | |||
t.Log(ret) | |||
t.Log(err) | |||
} | |||
func Test_Qqwry(t *testing.T) { | |||
loc, err := iploc.Open("qqwry.dat") | |||
if err != nil { | |||
panic(err) | |||
} | |||
detail := loc.Find("219.131.197.178") | |||
t.Log(detail.String()) | |||
t.Log(detail.Country, detail.Province, detail.City, detail.County) | |||
} |