Jelajahi Sumber

优化调整

Jerry 7 tahun lalu
induk
melakukan
261abe1c85
5 mengubah file dengan 114 tambahan dan 98 penghapusan
  1. 23 27
      README.md
  2. 7 1
      constant.go
  3. 18 12
      wechat_params.go
  4. 42 31
      wechat_pay.go
  5. 24 27
      wechat_pay_test.go

+ 23 - 27
README.md

@@ -7,11 +7,15 @@
 ### 微信支付 example
 
 ```
-	//New一个微信支付客户端,目前isDebug参数只支持false
-	client := NewWechatPayClient("wxdaa2ab9ef87123456", "136666666", false)
+	//初始化微信客户端
+	//    appId:应用ID
+	//    mchID:商户ID
+	//    isProd:是否是正式环境
+	//    secretKey:key,(当isProd为true时,此参数必传;false时,此参数为空)
+	client := NewWeChatClient(AppID, MchID, false)
 
 	//初始化参数结构体
-	params := new(WechatParams)
+	params := new(WeChatPayParams)
 	params.NonceStr = "dyUNIkNS29hvDUC1CmoF0alSdfCQGg9I"
 	params.Body = "测试充值"
 	params.OutTradeNo = "GYsadfjk4dhg3fkhffgnlsdkf"
@@ -20,33 +24,25 @@
 	params.NotifyUrl = "http://www.igoogle.ink"
 	params.TradeType = WX_PayType_JsApi //目前只支持JSAPI有效
 	params.DeviceInfo = "WEB"
-	params.SignType = WX_SignType_HMAC_SHA256 //如不设置此参数,默认为 MD5
-	params.Openid = "o0Df70H2Q0fY8JXh1aFPIRyOBgu81"
+	params.SignType = WX_SignType_MD5 //如不设置此参数,默认为 MD5
+	params.Openid = OpenID
 
-	//客户端设置参数
-	client.SetParams(params)
-
-	//传入secretKey获取Sign并重新设置参数
-	client.GetSignAndSetReqParam("GFDS8j98rewnmgl45wHTt980jg543wmg")
-
-	//请求支付,成功后得到结构
-	err := client.GoWechatPay()
+	//请求支付,成功后得到结果
+	wxRsp, err := client.GoWeChatPay(params)
 	if err != nil {
-		fmt.Println(err)
+		fmt.Println("Error:", err)
+	} else {
+		fmt.Println("ReturnCode:", wxRsp.ReturnCode)
+		fmt.Println("ReturnMsg:", wxRsp.ReturnMsg)
+		fmt.Println("Appid:", wxRsp.Appid)
+		fmt.Println("MchId:", wxRsp.MchId)
+		fmt.Println("DeviceInfo:", wxRsp.DeviceInfo)
+		fmt.Println("NonceStr:", wxRsp.NonceStr)
+		fmt.Println("Sign:", wxRsp.Sign)
+		fmt.Println("ResultCode:", wxRsp.ResultCode)
+		fmt.Println("PrepayId:", wxRsp.PrepayId)
+		fmt.Println("TradeType:", wxRsp.TradeType)
 	}
-	//err为空,请求支付成功后,输出请求结果
-	fmt.Println(client.WXRsp)
-
-	fmt.Println("ReturnCode:", client.WXRsp.ReturnCode)
-	fmt.Println("ReturnMsg:", client.WXRsp.ReturnMsg)
-	fmt.Println("Appid:", client.WXRsp.Appid)
-	fmt.Println("MchId:", client.WXRsp.MchId)
-	fmt.Println("DeviceInfo:", client.WXRsp.DeviceInfo)
-	fmt.Println("NonceStr:", client.WXRsp.NonceStr)
-	fmt.Println("Sign:", client.WXRsp.Sign)
-	fmt.Println("ResultCode:", client.WXRsp.ResultCode)
-	fmt.Println("PrepayId:", client.WXRsp.PrepayId)
-	fmt.Println("TradeType:", client.WXRsp.TradeType)
 ```
 
 ### 支付宝支付 example

+ 7 - 1
constant.go

@@ -3,7 +3,7 @@ package go_pay
 const (
 	//URL
 	WX_PayUrl        = "https://api.mch.weixin.qq.com/pay/unifiedorder"
-	WX_PayUrl_SanBox = "https://api.mch.weixin.qq.com/pay/unifiedorder"
+	WX_PayUrl_SanBox = "https://api.mch.weixin.qq.com/sandboxnew/pay/unifiedorder"
 
 	//支付类型
 	WX_PayType_Mini   = "JSAPI"
@@ -15,4 +15,10 @@ const (
 	//签名方式
 	WX_SignType_MD5         = "MD5"
 	WX_SignType_HMAC_SHA256 = "HMAC-SHA256"
+
+	//Debug数据
+	SecretKey = "GFDS8j98rewnmgl45wHTt980jg543wmg"
+	AppID     = "wxdaa2ab9ef87b5497"
+	MchID     = "1368139502"
+	OpenID    = "o0Df70H2Q0fY8JXh1aFPIRyOBgu8"
 )

+ 18 - 12
wechat_params.go

@@ -12,10 +12,10 @@ import (
 	"strings"
 )
 
-type WXReq map[string]string
+type WeChatRequestBody map[string]string
 
 //获取参数
-func (w WXReq) Get(key string) string {
+func (w WeChatRequestBody) Get(key string) string {
 	if w == nil {
 		return ""
 	}
@@ -24,12 +24,12 @@ func (w WXReq) Get(key string) string {
 }
 
 //设置参数
-func (w WXReq) Set(key string, value string) {
+func (w WeChatRequestBody) Set(key string, value string) {
 	w[key] = value
 }
 
 //删除参数
-func (w WXReq) Remove(key string) {
+func (w WeChatRequestBody) Remove(key string) {
 	delete(w, key)
 }
 
@@ -58,7 +58,7 @@ func (w WXReq) Remove(key string) {
 //    Openid: 用户标识: trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识.
 //    Receipt: Y,传入Y时,支付成功消息和支付详情页将出现开票入口。需要在微信支付商户平台或微信公众平台开通电子发票功能,传此字段才可生效.
 //    SceneInfo: 该字段常用于线下活动时的场景信息上报,支持上报实际门店信息,商户也可以按需求自己上报相关信息。该字段为JSON对象数据,对象格式为{"store_info":{"id": "门店ID","name": "名称","area_code": "编码","address": "地址" }}.
-type WechatParams struct {
+type WeChatPayParams struct {
 	NonceStr       string `xml:"nonce_str"`
 	Body           string `xml:"body"`
 	OutTradeNo     string `xml:"out_trade_no"`
@@ -91,9 +91,9 @@ type StoreInfo struct {
 }
 
 //获取请求支付的参数
-func (w *WechatParams) getRequestParams(appid, mchId string, params *WechatParams) WXReq {
-	reqs := make(WXReq)
-	reqs.Set("appid", appid)
+func (w *WeChatPayParams) getRequestParams(appId, mchId string, params *WeChatPayParams) WeChatRequestBody {
+	reqs := make(WeChatRequestBody)
+	reqs.Set("appid", appId)
 	reqs.Set("mch_id", mchId)
 	reqs.Set("nonce_str", params.NonceStr)
 	reqs.Set("body", params.Body)
@@ -149,9 +149,9 @@ func (w *WechatParams) getRequestParams(appid, mchId string, params *WechatParam
 }
 
 //获取Sign签名和请求支付的参数
-func getSignAndRequestParam(appid, mchId string, secretKey string, param *WechatParams) (sign string, reqs WXReq) {
+func getSignAndRequestParam(appId, mchId string, secretKey string, param *WeChatPayParams) (sign string, reqs WeChatRequestBody) {
 
-	reqs = param.getRequestParams(appid, mchId, param)
+	reqs = param.getRequestParams(appId, mchId, param)
 
 	signStr := getSignString(secretKey, reqs)
 	//fmt.Println("signStr:", signStr)
@@ -170,7 +170,7 @@ func getSignAndRequestParam(appid, mchId string, secretKey string, param *Wechat
 }
 
 //获取根据Key排序后的请求参数字符串
-func getSignString(secretKey string, wxReq WXReq) string {
+func getSignString(secretKey string, wxReq WeChatRequestBody) string {
 	keyList := make([]string, 0)
 	for k := range wxReq {
 		keyList = append(keyList, k)
@@ -188,7 +188,13 @@ func getSignString(secretKey string, wxReq WXReq) string {
 	return buffer.String()
 }
 
-func (w WXReq) generateXml() (reqXml string) {
+//获取Sanbox
+func getSanBoxSignString() {
+	//url:= "https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey"
+
+}
+
+func (w WeChatRequestBody) generateXml() (reqXml string) {
 	buffer := new(bytes.Buffer)
 	buffer.WriteString("<xml>")
 

+ 42 - 31
wechat_pay.go

@@ -3,9 +3,10 @@ package go_pay
 import (
 	"encoding/xml"
 	"github.com/parnurzeal/gorequest"
+	"github.com/pkg/errors"
 )
 
-type WechatPayResponse struct {
+type WeChatPayResponse struct {
 	ReturnCode string `xml:"return_code"`
 	ReturnMsg  string `xml:"return_msg"`
 	Appid      string `xml:"appid"`
@@ -18,55 +19,65 @@ type WechatPayResponse struct {
 	TradeType  string `xml:"trade_type"`
 }
 
-type WechatPayClient struct {
-	Appid    string
-	MchId    string
-	Params   *WechatParams
-	ReqParam WXReq
-	WXRsp    *WechatPayResponse
-	isDebug  bool
+type WeChatClient struct {
+	AppId     string
+	MchId     string
+	secretKey string
+	Params    *WeChatPayParams
+	ReqParam  WeChatRequestBody
+	isProd    bool
 }
 
-//    Appid: 微信支付分配的公众账号ID(企业号corpid即为此appId)
-//    MchId: 微信支付分配的商户号
-func NewWechatPayClient(appid, mchId string, isDebug bool) *WechatPayClient {
-	client := new(WechatPayClient)
-	client.Appid = appid
+//初始化微信客户端
+//    appId:应用ID
+//    mchID:商户ID
+//    isProd:是否是正式环境
+//    secretKey:key,(当isProd为true时,此参数必传;false时,此参数为空)
+func NewWeChatClient(appId, mchId string, isProd bool, secretKey ...string) *WeChatClient {
+	client := new(WeChatClient)
+	client.AppId = appId
 	client.MchId = mchId
-	client.isDebug = isDebug
-	client.WXRsp = new(WechatPayResponse)
+	client.isProd = isProd
+	if isProd && len(secretKey) > 0 {
+		client.secretKey = secretKey[0]
+	}
 	return client
 }
 
-//设置参数
-func (this *WechatPayClient) SetParams(param *WechatParams) {
+//支付
+func (this *WeChatClient) GoWeChatPay(param *WeChatPayParams) (wxRsp *WeChatPayResponse, err error) {
 	this.Params = param
-}
-
-func (this *WechatPayClient) GetSignAndSetReqParam(secretKey string) string {
-	sign, reqs := getSignAndRequestParam(this.Appid, this.MchId, secretKey, this.Params)
+	//fmt.Println("reqs:", this.ReqParam)
+	var sign string
+	var reqs WeChatRequestBody
+	if this.isProd {
+		sign, reqs = getSignAndRequestParam(this.AppId, this.MchId, this.secretKey, this.Params)
+	} else {
+		return nil, errors.New("暂不支持沙箱测试")
+		//getSanBoxSignString(this.Appid, this.MchId, this.Params)
+	}
 	this.ReqParam = reqs
 	this.ReqParam.Set("sign", sign)
-	return sign
-}
 
-//APP支付
-func (this *WechatPayClient) GoWechatPay() (err error) {
-	//fmt.Println("reqs:", this.ReqParam)
 	reqXML := this.ReqParam.generateXml()
 	agent := gorequest.New()
-	agent.Post(WX_PayUrl)
+	if this.isProd {
+		agent.Post(WX_PayUrl)
+	} else {
+		agent.Post(WX_PayUrl_SanBox)
+	}
 	agent.Type("xml")
 	agent.SendString(reqXML)
 	response, bytes, errs := agent.EndBytes()
 	defer response.Body.Close()
 	if len(errs) > 0 {
-		return errs[0]
+		return nil, errs[0]
 	}
 	//fmt.Println("bytes:", string(bytes))
-	err = xml.Unmarshal(bytes, this.WXRsp)
+	wxRsp = new(WeChatPayResponse)
+	err = xml.Unmarshal(bytes, wxRsp)
 	if err != nil {
-		return err
+		return nil, err
 	}
-	return nil
+	return wxRsp, nil
 }

+ 24 - 27
wechat_pay_test.go

@@ -6,11 +6,16 @@ import (
 )
 
 func TestWXPay(t *testing.T) {
-	//New一个微信支付客户端,目前isDebug参数只支持false
-	client := NewWechatPayClient("wxdaa2ab9ef87b54971", "13681395021", false)
+
+	//初始化微信客户端
+	//    appId:应用ID
+	//    mchID:商户ID
+	//    isProd:是否是正式环境
+	//    secretKey:key,(当isProd为true时,此参数必传;false时,此参数为空)
+	client := NewWeChatClient(AppID, MchID, false)
 
 	//初始化参数结构体
-	params := new(WechatParams)
+	params := new(WeChatPayParams)
 	params.NonceStr = "dyUNIkNS29hvDUC1CmoF0alSdfCQGg9I"
 	params.Body = "测试充值"
 	params.OutTradeNo = "GYsadfjk4dhg3fkhffgnlsdkf"
@@ -19,31 +24,23 @@ func TestWXPay(t *testing.T) {
 	params.NotifyUrl = "http://www.igoogle.ink"
 	params.TradeType = WX_PayType_JsApi //目前只支持JSAPI有效
 	params.DeviceInfo = "WEB"
-	params.SignType = WX_SignType_HMAC_SHA256 //如不设置此参数,默认为 MD5
-	params.Openid = "o0Df70H2Q0fY8JXh1aFPIRyOBgu81"
-
-	//客户端设置参数
-	client.SetParams(params)
+	params.SignType = WX_SignType_MD5 //如不设置此参数,默认为 MD5
+	params.Openid = OpenID
 
-	//传入secretKey获取Sign并重新设置参数
-	client.GetSignAndSetReqParam("GFDS8j98rewnmgl45wHTt980jg543wmg1")
-
-	//请求支付,成功后得到结构
-	err := client.GoWechatPay()
+	//请求支付,成功后得到结果
+	wxRsp, err := client.GoWeChatPay(params)
 	if err != nil {
-		fmt.Println(err)
+		fmt.Println("Error:", err)
+	} else {
+		fmt.Println("ReturnCode:", wxRsp.ReturnCode)
+		fmt.Println("ReturnMsg:", wxRsp.ReturnMsg)
+		fmt.Println("Appid:", wxRsp.Appid)
+		fmt.Println("MchId:", wxRsp.MchId)
+		fmt.Println("DeviceInfo:", wxRsp.DeviceInfo)
+		fmt.Println("NonceStr:", wxRsp.NonceStr)
+		fmt.Println("Sign:", wxRsp.Sign)
+		fmt.Println("ResultCode:", wxRsp.ResultCode)
+		fmt.Println("PrepayId:", wxRsp.PrepayId)
+		fmt.Println("TradeType:", wxRsp.TradeType)
 	}
-	//err为空,请求支付成功后,输出请求结果
-	fmt.Println(client.WXRsp)
-
-	fmt.Println("ReturnCode:", client.WXRsp.ReturnCode)
-	fmt.Println("ReturnMsg:", client.WXRsp.ReturnMsg)
-	fmt.Println("Appid:", client.WXRsp.Appid)
-	fmt.Println("MchId:", client.WXRsp.MchId)
-	fmt.Println("DeviceInfo:", client.WXRsp.DeviceInfo)
-	fmt.Println("NonceStr:", client.WXRsp.NonceStr)
-	fmt.Println("Sign:", client.WXRsp.Sign)
-	fmt.Println("ResultCode:", client.WXRsp.ResultCode)
-	fmt.Println("PrepayId:", client.WXRsp.PrepayId)
-	fmt.Println("TradeType:", client.WXRsp.TradeType)
 }