diff --git a/app/constants/common/common.go b/app/constants/common/common.go index 3d2e07c..0f7a798 100644 --- a/app/constants/common/common.go +++ b/app/constants/common/common.go @@ -6,6 +6,8 @@ const ( ADMIN_V1 = "/pay/admin/api/v1" FRONT_V1 = "/pay/front/api/v1" + WXCodeRedirectAddress = FRONT_V1 + "/wx/payurl" // 微信支付,授权code后 重定向地址 + // 支付渠道枚举,1微信JSAPI,2微信H5,3微信app,4微信Native,5微信小程序,6支付宝网页&移动应用,7支付宝小程序,8支付宝JSAPI PAY_CHANNEL_UNKNOWN = 0 PAY_CHANNEL_WECHAT_JSAPI = 1 diff --git a/app/constants/errorcode/error_code.go b/app/constants/errorcode/error_code.go index d452264..d0647cc 100644 --- a/app/constants/errorcode/error_code.go +++ b/app/constants/errorcode/error_code.go @@ -98,7 +98,8 @@ const ( RefundOutTradeNoSame = 1801 // 微信授权 - WechatAuthFail = 1901 + WechatAuthFail = 1901 + WechatAuthSignFail = 1902 ) var MsgEN = map[int]string{ @@ -182,7 +183,8 @@ var MsgZH = map[int]string{ ThirdRefundFail: "第三方退款失败", - WechatAuthFail: "微信授权失败", + WechatAuthFail: "微信授权失败", + WechatAuthSignFail: "微信签名失败", } var MsgMap map[string]map[int]string = map[string]map[int]string{"en": MsgZH} diff --git a/app/http/controllers/front/payment_controller.go b/app/http/controllers/front/payment_controller.go index 26f5596..fdde9be 100644 --- a/app/http/controllers/front/payment_controller.go +++ b/app/http/controllers/front/payment_controller.go @@ -7,6 +7,7 @@ import ( "PaymentCenter/app/http/entities/front" "PaymentCenter/app/models/paychannelmodel" "PaymentCenter/app/services" + "PaymentCenter/app/services/thirdpay" "PaymentCenter/app/third/paymentService" "encoding/json" "fmt" @@ -197,17 +198,42 @@ func Index(c *gin.Context) { c.HTML(200, "index.html", gin.H{}) } -// 获取微信授权链接 +// 拼接微信授权链接 func GetWxAuthUrl(c *gin.Context) { req, _ := controllers.GetRequest(c).(*front.GetWxAuthUrlRequest) - url, code := services.GetWxAuthUrl(*req) + url, code := thirdpay.GetWxAuthUrl(*req) controllers.HandCodeRes(c, url, code) } // 通过code获取授权,openid func GetWxAuth(c *gin.Context) { req, _ := controllers.GetRequest(c).(*front.GetWxAuthRequest) - rsp, code := services.GetWxAuth(*req) + rsp, code := thirdpay.GetWxAuth(*req) + controllers.HandCodeRes(c, rsp, code) +} + +// 接收code +func GetWxCode(c *gin.Context) { + req, _ := controllers.GetRequest(c).(*front.GetWxAuthRequest) + //rsp, code := thirdpay.GetWxAuth(*req) + controllers.HandCodeRes(c, req, 200) +} + +// 微信JSAPI 支付接口 +/* +1.订单请求参数 +2.订单信息存数据 +3.返回用户授权地址 +4.用户授权后获取code +5.通过code获取openid +6.通过openid请求微信下单,返回支付参数 +7.支付参数聚合,签名,返回支付参数给前端 +*/ +func WxJsApiPay(c *gin.Context) { + req, _ := controllers.GetRequest(c).(*front.WxJsApiPayRequest) + req.ClientIp = c.ClientIP() + + rsp, code := thirdpay.WxJsApiPay(*req) controllers.HandCodeRes(c, rsp, code) } diff --git a/app/http/entities/front/wechat.go b/app/http/entities/front/wechat.go index a5da351..42cefae 100644 --- a/app/http/entities/front/wechat.go +++ b/app/http/entities/front/wechat.go @@ -5,8 +5,8 @@ type GetWxAuthUrlRequest struct { } type GetWxAuthRequest struct { - Code string `json:"code" form:"code" ` - State string `json:"state" form:"state"` + Code string `json:"code" form:"code" ` + PayChannelId string `json:"state" form:"state"` } // 获取微信用户信息 @@ -19,3 +19,27 @@ type GetWxAuthResponse struct { IsSnapshotuser int `json:"is_snapshotuser"` Unionid string `json:"unionid"` // 用户统一标识(针对一个微信开放平台账号下的应用,同一用户的 unionid 是唯一的),只有当scope为"snsapi_userinfo"时返回 } + +// jsapi支付 +type WxJsApiPayRequest struct { + Code string `json:"code" form:"code" ` + State string `json:"state" form:"state"` // 支付中心的订单id + ClientIp string `json:"client_ip" form:"client_ip"` +} + +//// jsapi支付返回 +//type WxJsApiPayResponse struct { +// Url string +// ThirdMsg string +//} + +// jsapi支付返回 +type WxJsApiPayResponse struct { + AppId string `json:"appId"` + TimeStamp string `json:"timeStamp"` + NonceStr string `json:"nonceStr"` + Package string `json:"package"` + SignType string `json:"signType"` + PaySign string `json:"paySign"` + ThirdMsg string `json:"third_msg"` +} diff --git a/app/http/requestmapping/front.go b/app/http/requestmapping/front.go index 9d6385e..a1bcfc5 100644 --- a/app/http/requestmapping/front.go +++ b/app/http/requestmapping/front.go @@ -22,4 +22,7 @@ var FrontRequestMapBeforeDecrypt = map[string]func() interface{}{ common.FRONT_V1 + "/wx/index": func() interface{} { return new(entities.PageRequest) }, common.FRONT_V1 + "/wx/getWxAuthUrl": func() interface{} { return new(front.GetWxAuthUrlRequest) }, common.FRONT_V1 + "/wx/getWxAuth": func() interface{} { return new(front.GetWxAuthRequest) }, + common.FRONT_V1 + "/wx/getCode": func() interface{} { return new(front.GetWxAuthRequest) }, + + common.WXCodeRedirectAddress: func() interface{} { return new(front.WxJsApiPayRequest) }, } diff --git a/app/http/routes/route.go b/app/http/routes/route.go index 4ef94fa..cad1444 100644 --- a/app/http/routes/route.go +++ b/app/http/routes/route.go @@ -72,10 +72,13 @@ func RegisterRoute(router *gin.Engine) { wx := v1.Group("/wx", middlewares.ValidateRequest()) { wx.GET("/index", front.Index) // 获取页面 - wx.POST("/getWxAuthUrl", front.GetWxAuthUrl) // 获取授权code + wx.POST("/getWxAuthUrl", front.GetWxAuthUrl) // 获取授权codeUrl wx.GET("/getWxAuth", front.GetWxAuth) // 获取openId + wx.GET("/getCode", front.GetWxCode) // 接收微信code } + router.GET(common.WXCodeRedirectAddress, middlewares.ValidateRequest(), front.WxJsApiPay) + router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) } diff --git a/app/services/thirdpay/do/pay.go b/app/services/thirdpay/do/pay.go index 32d8ce2..8162bf9 100644 --- a/app/services/thirdpay/do/pay.go +++ b/app/services/thirdpay/do/pay.go @@ -8,7 +8,10 @@ import ( "PaymentCenter/app/services" "PaymentCenter/app/third/paymentService/payCommon" "PaymentCenter/app/utils" + "PaymentCenter/config" "context" + "net/url" + "strconv" "xorm.io/builder" "PaymentCenter/app/models/ordersmodel" @@ -99,6 +102,7 @@ func (w *Pay) PayUrl() (url string) { var ( payFunc func(commonPayInfo *paymentService.PayOrderRequest, channel *paychannelmodel.PayChannel) error ok bool + res paymentService.PayOrderResponse ) thirdPay := &paymentService.PayOrderRequest{ PayChannelId: w.PayParam.Channel.Id, @@ -120,7 +124,20 @@ func (w *Pay) PayUrl() (url string) { w.PayCode = errorcode.PayChannelExtJsonError return } - res := paymentService.PaymentService(*w.ctx, *thirdPay) + switch w.PayParam.Channel.ChannelType { + // 微信公众号支付,返回的是用户授权链接 + case common.PAY_CHANNEL_WECHAT_JSAPI: + // 获取授权链接 + res.Result, res.Code = w.GetWxAuthUrl(w.PayParam.Channel.AppId, w.Order.Id) + case common.PAY_CHANNEL_ALIPAY_WEB | common.PAY_CHANNEL_WECHAT_H5: + res = paymentService.PaymentService(*w.ctx, *thirdPay) + + default: + w.PayCode = errorcode.PayChannelNotBuild + return + } + + //res := paymentService.PaymentService(*w.ctx, *thirdPay) if res.Code == payCommon.PAY_SUCCESS_CODE { w.Order.Status = common.ORDER_STATUS_PAYING @@ -208,3 +225,20 @@ func (w *Pay) CloseOrder() { w.ThirdMsg = res.ErrorMsg w.PayCode = res.Code } + +// appid:微信的公众号appid +func (w *Pay) GetWxAuthUrl(appid string, orderId int64) (targetUrl string, code int) { + var ( + // 重定向地址 + redirectUri = config.GetConf().PayService.Host + common.WXCodeRedirectAddress + ) + baseUrl := "https://open.weixin.qq.com/connect/oauth2/authorize" + redirectUri = url.QueryEscape(redirectUri) + responseType := "code" + scope := "snsapi_base" + order := strconv.Itoa(int(orderId)) + + targetUrl = baseUrl + "?appid=" + appid + "&redirect_uri=" + redirectUri + "&response_type=" + responseType + "&scope=" + scope + "&state=" + order + "#wechat_redirect" + code = errorcode.Success + return +} diff --git a/app/services/thirdpay/wx.go b/app/services/thirdpay/wx.go new file mode 100644 index 0000000..e9803c8 --- /dev/null +++ b/app/services/thirdpay/wx.go @@ -0,0 +1,319 @@ +package thirdpay + +import ( + "PaymentCenter/app/constants/common" + "PaymentCenter/app/constants/errorcode" + "PaymentCenter/app/http/entities/front" + "PaymentCenter/app/models/ordersmodel" + "PaymentCenter/app/models/paychannelmodel" + "PaymentCenter/app/services" + "PaymentCenter/app/third/paymentService" + "PaymentCenter/app/third/paymentService/payCommon" + "PaymentCenter/app/utils" + "PaymentCenter/app/utils/httpclient" + "PaymentCenter/config" + "context" + "crypto" + "crypto/rsa" + "crypto/sha256" + "crypto/x509" + "encoding/base64" + "encoding/json" + "encoding/pem" + "errors" + "fmt" + "net/url" + "strconv" + "time" + "xorm.io/builder" +) + +// 获取授权链接 +func GetWxAuthUrl(param front.GetWxAuthUrlRequest) (targetUrl string, code int) { + var ( + // 重定向地址 + redirectUri = config.GetConf().PayService.Host + common.WXCodeRedirectAddress + ) + baseUrl := "https://open.weixin.qq.com/connect/oauth2/authorize" + + // 获取支付渠道的配置 + id, err := strconv.Atoi(param.PayChannelId) + if err != nil { + code = handErr(err) + return + } + payChannel := paychannelmodel.PayChannel{Id: int64(id)} + code = services.PayChannelGet(&payChannel) + if code != 200 { + return + } + + appid := payChannel.AppId + redirectUri = url.QueryEscape(redirectUri) + responseType := "code" + scope := "snsapi_base" + + targetUrl = baseUrl + "?appid=" + appid + "&redirect_uri=" + redirectUri + "&response_type=" + responseType + "&scope=" + scope + "&state=" + param.PayChannelId + "#wechat_redirect" + return +} + +// // 通过code换取网页授权access_token,openid +func GetWxAuth(param front.GetWxAuthRequest) (rsp front.GetWxAuthResponse, code int) { + + // 获取支付渠道的配置 + id, err := strconv.Atoi(param.PayChannelId) + if err != nil { + code = handErr(err) + return + } + payChannel := paychannelmodel.PayChannel{Id: int64(id)} + code = services.PayChannelGet(&payChannel) + if code != 200 { + return + } + + //// 配置支付的解析 + wxConfig := make(map[string]interface{}) + err = json.Unmarshal([]byte(payChannel.ExtJson), &wxConfig) + if err != nil { + code = handErr(err) + return + } + sk := wxConfig["secret"].(string) + if sk == "" { + code = errorcode.PayChannelConfigNotFound + return + } + + targetUrl := fmt.Sprintf("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", + payChannel.AppId, + sk, + param.Code, + ) + + header := map[string]string{ + "Content-Type": "application/json", + } + body := map[string]string{} + response, err := httpclient.FastHttpGet(targetUrl, header, body, 0) + if err != nil { + code = handErr(err) + return + } + utils.Log(nil, "获取微信授权信息", string(response), targetUrl) + + // 解析返回数据 + err = json.Unmarshal(response, &rsp) + if err != nil { + code = handErr(err) + return + } + if rsp.Openid == "" { + code = errorcode.WechatAuthFail + return + } + code = handErr(err) + return +} + +// 微信JSAPI 支付接口 +/* +1.获取订单请求参数 +2.订单信息存数据 +3.返回用户授权地址 +4.用户授权后获取code +5.通过code获取openid +6.通过openid请求微信下单,返回支付参数 +7.支付参数聚合,签名,返回支付参数给前端 +*/ +type wxJsapiPay struct { + code int + msg string + param front.WxJsApiPayRequest + order *ordersmodel.Orders + payChannel paychannelmodel.PayChannel + wxConfig map[string]interface{} + + openId string // 用户openid +} + +func newWxJsapiPay(param front.WxJsApiPayRequest) *wxJsapiPay { + return &wxJsapiPay{param: param} +} + +func (this *wxJsapiPay) getOrder() { + order := new(ordersmodel.Orders) + this.order, this.code = services.OrderFindOne(order, builder.Eq{"id": this.param.State}) +} +func (this *wxJsapiPay) getPayChannel() { + payChannel := paychannelmodel.PayChannel{Id: this.order.PayChannelId} + this.code = services.PayChannelGet(&payChannel) + this.payChannel = payChannel +} + +func (this *wxJsapiPay) getOpenId() { + var err error + //// 配置支付的解析 + wxConfig := make(map[string]interface{}) + err = json.Unmarshal([]byte(this.payChannel.ExtJson), &wxConfig) + if err != nil { + this.code = handErr(err) + return + } + sk := wxConfig["secret"].(string) + if sk == "" { + this.code = errorcode.PayChannelConfigNotFound + return + } + this.wxConfig = wxConfig + + targetUrl := fmt.Sprintf("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", + this.payChannel.AppId, + sk, + this.param.Code, + ) + + header := map[string]string{ + "Content-Type": "application/json", + } + body := map[string]string{} + response, err := httpclient.FastHttpGet(targetUrl, header, body, 0) + if err != nil { + this.code = handErr(err) + return + } + utils.Log(nil, "获取微信授权信息", string(response), targetUrl) + + // 解析返回数据 + var rsp front.GetWxAuthResponse + err = json.Unmarshal(response, &rsp) + if err != nil { + this.code = handErr(err) + return + } + if rsp.Openid == "" { + this.code = errorcode.WechatAuthFail + return + } + this.openId = rsp.Openid + this.code = handErr(err) +} + +func (this *wxJsapiPay) Sign(AppId, TimeStamp, NonceStr, Package string) (res string, err error) { + //组装被加密的字符串 + + targetStr := AppId + "\n" + TimeStamp + "\n" + NonceStr + "\n" + Package + "\n" + //加密 + sign, err := this.SHA256WithRsaBase64(targetStr) + + return sign, err +} + +func (this *wxJsapiPay) SHA256WithRsaBase64(origData string) (sign string, err error) { + //var keypath = "商户证书私钥地址" + //key, err := ioutil.ReadFile(keypath) + var key []byte + if pri, ok := this.wxConfig["private_key"].(string); ok { + key = []byte(pri) + } else { + return "", errors.New("配置的私钥不存在") + } + + blocks, _ := pem.Decode(key) + if blocks == nil || blocks.Type != "PRIVATE KEY" { + utils.Log(nil, "failed to decode PRIVATE KEY") + return + + } + privateKey, err := x509.ParsePKCS8PrivateKey(blocks.Bytes) + + h := sha256.New() + h.Write([]byte(origData)) + digest := h.Sum(nil) + s, _ := rsa.SignPKCS1v15(nil, privateKey.(*rsa.PrivateKey), crypto.SHA256, digest) + sign = base64.StdEncoding.EncodeToString(s) + + return sign, err +} + +func WxJsApiPay(param front.WxJsApiPayRequest) (response front.WxJsApiPayResponse, code int) { + var ctx = context.Background() + task := newWxJsapiPay(param) + + // 1 获取订单 + task.getOrder() + if task.code != errorcode.Success { + return response, task.code + } + + // 获取支付渠道配置 + task.getPayChannel() + if task.code != errorcode.Success { + return response, task.code + } + + // 2 通过code获取openid + task.getOpenId() + if task.code != errorcode.Success { + return response, task.code + } + + order := task.order + // 通过openid,订单数据,请求微信下单, 获取prepay_id + orderRequest := paymentService.PayOrderRequest{ + PayChannelId: order.PayChannelId, + OrderId: order.Id, + ChannelType: task.payChannel.ChannelType, + Description: order.Desc, + Amount: order.Amount, + PayerClientIp: param.ClientIp, + ReturnUrl: "", + //Wx: paymentService.WxPay{}, + //Ali: paymentService.AliPay{}, + OpenId: task.openId, + } + res := paymentService.PaymentService(ctx, orderRequest) + // 下单失败 + if res.Code != payCommon.PAY_SUCCESS_CODE { + task.code = errorcode.PrePayFail + task.msg = res.ErrorMsg + return response, task.code + } + // 更新订单状态 + order.Status = common.ORDER_STATUS_PAYING + task.code = services.OrderUpdate(order, "status") + if task.code != errorcode.Success { + utils.Log(nil, "成功下单,更新订单状态失败", order) + } + + // 3 组装返回数据 + response = front.WxJsApiPayResponse{ + AppId: task.payChannel.AppId, + TimeStamp: strconv.Itoa(int(time.Now().Unix())), + NonceStr: strconv.Itoa(int(time.Now().Unix())), + Package: "prepay_id=" + res.Result, + SignType: "RSA", + PaySign: "", + ThirdMsg: "", + } + + // 4 签名 + // 4.1 签名数据 + signValue, err := task.Sign(response.AppId, response.TimeStamp, response.NonceStr, response.Package) + if err != nil { + utils.Log(nil, "签名失败", err) + return response, errorcode.WechatAuthFail + } + response.PaySign = signValue + + return response, task.code +} + +func handErr(err error) int { + if err != nil { + utils.Log(nil, "sys err", err.Error()) + return errorcode.SystemError + } else { + return errorcode.Success + } +} diff --git a/app/services/wecaht.go b/app/services/wecaht.go index 7797b3a..6f8a27c 100644 --- a/app/services/wecaht.go +++ b/app/services/wecaht.go @@ -1,110 +1,316 @@ package services -import ( - "PaymentCenter/app/constants/common" - "PaymentCenter/app/constants/errorcode" - "PaymentCenter/app/http/entities/front" - "PaymentCenter/app/models/paychannelmodel" - "PaymentCenter/app/utils" - "PaymentCenter/app/utils/httpclient" - "PaymentCenter/config" - "encoding/json" - "fmt" - "net/url" - "strconv" -) - -// 获取授权链接 -func GetWxAuthUrl(param front.GetWxAuthUrlRequest) (targetUrl string, code int) { - var ( - // 重定向地址 - redirectUri = config.GetConf().PayService.Host + common.FRONT_V1 + "/wx/getWxAuth" - ) - baseUrl := "https://open.weixin.qq.com/connect/oauth2/authorize" - - // 获取支付渠道的配置 - id, err := strconv.Atoi(param.PayChannelId) - if err != nil { - code = handErr(err) - return - } - payChannel := paychannelmodel.PayChannel{Id: int64(id)} - code = PayChannelGet(&payChannel) - if code != 200 { - return - } - //// 配置解析 - //wxConfig := paymentService.WxPay{} - //err = json.Unmarshal([]byte(payChannel.ExtJson), &wxConfig) - //if err != nil { - // code = handErr(err) - // return - //} - - appid := payChannel.AppId - redirectUri = url.QueryEscape(redirectUri) - responseType := "code" - scope := "snsapi_base" - - targetUrl = baseUrl + "?appid=" + appid + "&redirect_uri=" + redirectUri + "&response_type=" + responseType + "&scope=" + scope + "&state=" + param.PayChannelId + "#wechat_redirect" - return -} - -// // 通过code换取网页授权access_token,openid -func GetWxAuth(param front.GetWxAuthRequest) (rsp front.GetWxAuthResponse, code int) { - - // 获取支付渠道的配置 - id, err := strconv.Atoi(param.State) - if err != nil { - code = handErr(err) - return - } - payChannel := paychannelmodel.PayChannel{Id: int64(id)} - code = PayChannelGet(&payChannel) - if code != 200 { - return - } - - //// 配置支付的解析 - wxConfig := make(map[string]interface{}) - err = json.Unmarshal([]byte(payChannel.ExtJson), &wxConfig) - if err != nil { - code = handErr(err) - return - } - sk := wxConfig["secret"].(string) - if sk == "" { - code = errorcode.PayChannelConfigNotFound - return - } - - targetUrl := fmt.Sprintf("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", - payChannel.AppId, - sk, - param.Code, - ) - - header := map[string]string{ - "Content-Type": "application/json", - } - body := map[string]string{} - response, err := httpclient.FastHttpGet(targetUrl, header, body, 0) - if err != nil { - code = handErr(err) - return - } - utils.Log(nil, "获取微信授权信息", string(response), targetUrl) - - // 解析返回数据 - err = json.Unmarshal(response, &rsp) - if err != nil { - code = handErr(err) - return - } - if rsp.Openid == "" { - code = errorcode.WechatAuthFail - return - } - code = handErr(err) - return -} +//import ( +// "PaymentCenter/app/constants/common" +// "PaymentCenter/app/constants/errorcode" +// "PaymentCenter/app/http/entities/front" +// "PaymentCenter/app/models/ordersmodel" +// "PaymentCenter/app/models/paychannelmodel" +// "PaymentCenter/app/third/paymentService" +// "PaymentCenter/app/third/paymentService/payCommon" +// "PaymentCenter/app/utils" +// "PaymentCenter/app/utils/httpclient" +// "PaymentCenter/config" +// "context" +// "crypto" +// "crypto/rsa" +// "crypto/sha256" +// "crypto/x509" +// "encoding/base64" +// "encoding/json" +// "encoding/pem" +// "errors" +// "fmt" +// "net/url" +// "strconv" +// "time" +// "xorm.io/builder" +//) +// +//// 获取授权链接 +//func GetWxAuthUrl(param front.GetWxAuthUrlRequest) (targetUrl string, code int) { +// var ( +// // 重定向地址 +// redirectUri = config.GetConf().PayService.Host + common.FRONT_V1 + "/wx/getWxAuth" +// ) +// baseUrl := "https://open.weixin.qq.com/connect/oauth2/authorize" +// +// // 获取支付渠道的配置 +// id, err := strconv.Atoi(param.PayChannelId) +// if err != nil { +// code = handErr(err) +// return +// } +// payChannel := paychannelmodel.PayChannel{Id: int64(id)} +// code = PayChannelGet(&payChannel) +// if code != 200 { +// return +// } +// //// 配置解析 +// //wxConfig := paymentService.WxPay{} +// //err = json.Unmarshal([]byte(payChannel.ExtJson), &wxConfig) +// //if err != nil { +// // code = handErr(err) +// // return +// //} +// +// appid := payChannel.AppId +// redirectUri = url.QueryEscape(redirectUri) +// responseType := "code" +// scope := "snsapi_base" +// +// targetUrl = baseUrl + "?appid=" + appid + "&redirect_uri=" + redirectUri + "&response_type=" + responseType + "&scope=" + scope + "&state=" + param.PayChannelId + "#wechat_redirect" +// return +//} +// +//// // 通过code换取网页授权access_token,openid +//func GetWxAuth(param front.GetWxAuthRequest) (rsp front.GetWxAuthResponse, code int) { +// +// // 获取支付渠道的配置 +// id, err := strconv.Atoi(param.PayChannelId) +// if err != nil { +// code = handErr(err) +// return +// } +// payChannel := paychannelmodel.PayChannel{Id: int64(id)} +// code = PayChannelGet(&payChannel) +// if code != 200 { +// return +// } +// +// //// 配置支付的解析 +// wxConfig := make(map[string]interface{}) +// err = json.Unmarshal([]byte(payChannel.ExtJson), &wxConfig) +// if err != nil { +// code = handErr(err) +// return +// } +// sk := wxConfig["secret"].(string) +// if sk == "" { +// code = errorcode.PayChannelConfigNotFound +// return +// } +// +// targetUrl := fmt.Sprintf("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", +// payChannel.AppId, +// sk, +// param.Code, +// ) +// +// header := map[string]string{ +// "Content-Type": "application/json", +// } +// body := map[string]string{} +// response, err := httpclient.FastHttpGet(targetUrl, header, body, 0) +// if err != nil { +// code = handErr(err) +// return +// } +// utils.Log(nil, "获取微信授权信息", string(response), targetUrl) +// +// // 解析返回数据 +// err = json.Unmarshal(response, &rsp) +// if err != nil { +// code = handErr(err) +// return +// } +// if rsp.Openid == "" { +// code = errorcode.WechatAuthFail +// return +// } +// code = handErr(err) +// return +//} +// +//// 微信JSAPI 支付接口 +///* +//1.获取订单请求参数 +//2.订单信息存数据 +//3.返回用户授权地址 +//4.用户授权后获取code +//5.通过code获取openid +//6.通过openid请求微信下单,返回支付参数 +//7.支付参数聚合,签名,返回支付参数给前端 +//*/ +//type wxJsapiPay struct { +// code int +// msg string +// param front.WxJsApiPayRequest +// order *ordersmodel.Orders +// payChannel paychannelmodel.PayChannel +// wxConfig map[string]interface{} +// +// openId string // 用户openid +//} +// +//func newWxJsapiPay(param front.WxJsApiPayRequest) *wxJsapiPay { +// return &wxJsapiPay{param: param} +//} +// +//func (this *wxJsapiPay) getOrder() { +// order := new(ordersmodel.Orders) +// this.order, this.code = OrderFindOne(order, builder.Eq{"id": this.param.State}) +//} +//func (this *wxJsapiPay) getPayChannel() { +// payChannel := paychannelmodel.PayChannel{Id: this.order.PayChannelId} +// this.code = PayChannelGet(&payChannel) +// this.payChannel = payChannel +//} +// +//func (this *wxJsapiPay) getOpenId() { +// var err error +// //// 配置支付的解析 +// wxConfig := make(map[string]interface{}) +// err = json.Unmarshal([]byte(this.payChannel.ExtJson), &wxConfig) +// if err != nil { +// this.code = handErr(err) +// return +// } +// sk := wxConfig["secret"].(string) +// if sk == "" { +// this.code = errorcode.PayChannelConfigNotFound +// return +// } +// this.wxConfig = wxConfig +// +// targetUrl := fmt.Sprintf("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", +// this.payChannel.AppId, +// sk, +// this.param.Code, +// ) +// +// header := map[string]string{ +// "Content-Type": "application/json", +// } +// body := map[string]string{} +// response, err := httpclient.FastHttpGet(targetUrl, header, body, 0) +// if err != nil { +// this.code = handErr(err) +// return +// } +// utils.Log(nil, "获取微信授权信息", string(response), targetUrl) +// +// // 解析返回数据 +// var rsp front.GetWxAuthResponse +// err = json.Unmarshal(response, &rsp) +// if err != nil { +// this.code = handErr(err) +// return +// } +// if rsp.Openid == "" { +// this.code = errorcode.WechatAuthFail +// return +// } +// this.openId = rsp.Openid +// this.code = handErr(err) +//} +// +//func (this *wxJsapiPay) Sign(AppId, TimeStamp, NonceStr, Package string) (res string, err error) { +// //组装被加密的字符串 +// +// targetStr := AppId + "\n" + TimeStamp + "\n" + NonceStr + "\n" + Package + "\n" +// //加密 +// sign, err := this.SHA256WithRsaBase64(targetStr) +// +// return sign, err +//} +// +//func (this *wxJsapiPay) SHA256WithRsaBase64(origData string) (sign string, err error) { +// //var keypath = "商户证书私钥地址" +// //key, err := ioutil.ReadFile(keypath) +// var key []byte +// if pri, ok := this.wxConfig["private_key"].(string); ok { +// key = []byte(pri) +// } else { +// return "", errors.New("配置的私钥不存在") +// } +// +// blocks, _ := pem.Decode(key) +// if blocks == nil || blocks.Type != "PRIVATE KEY" { +// utils.Log(nil, "failed to decode PRIVATE KEY") +// return +// +// } +// privateKey, err := x509.ParsePKCS8PrivateKey(blocks.Bytes) +// +// h := sha256.New() +// h.Write([]byte(origData)) +// digest := h.Sum(nil) +// s, _ := rsa.SignPKCS1v15(nil, privateKey.(*rsa.PrivateKey), crypto.SHA256, digest) +// sign = base64.StdEncoding.EncodeToString(s) +// +// return sign, err +//} +// +//func WxJsApiPay(param front.WxJsApiPayRequest) (response front.WxJsApiPayResponse, code int) { +// var ctx = context.Background() +// task := newWxJsapiPay(param) +// +// // 1 获取订单 +// task.getOrder() +// if task.code != errorcode.Success { +// return response, task.code +// } +// +// // 获取支付渠道配置 +// task.getPayChannel() +// if task.code != errorcode.Success { +// return response, task.code +// } +// +// // 2 通过code获取openid +// task.getOpenId() +// if task.code != errorcode.Success { +// return response, task.code +// } +// +// order := task.order +// // 通过openid,订单数据,请求微信下单, 获取prepay_id +// orderRequest := paymentService.PayOrderRequest{ +// PayChannelId: order.PayChannelId, +// OrderId: order.Id, +// ChannelType: task.payChannel.ChannelType, +// Description: order.Desc, +// Amount: order.Amount, +// PayerClientIp: param.ClientIp, +// ReturnUrl: "", +// //Wx: paymentService.WxPay{}, +// //Ali: paymentService.AliPay{}, +// OpenId: task.openId, +// } +// res := paymentService.PaymentService(ctx, orderRequest) +// // 下单失败 +// if res.Code != payCommon.PAY_SUCCESS_CODE { +// task.code = errorcode.PrePayFail +// task.msg = res.ErrorMsg +// return response, task.code +// } +// // 更新订单状态 +// order.Status = common.ORDER_STATUS_PAYING +// task.code = OrderUpdate(order, "status") +// if task.code != errorcode.Success { +// utils.Log(nil, "成功下单,更新订单状态失败", order) +// } +// +// // 3 组装返回数据 +// response = front.WxJsApiPayResponse{ +// AppId: task.payChannel.AppId, +// TimeStamp: strconv.Itoa(int(time.Now().Unix())), +// NonceStr: strconv.Itoa(int(time.Now().Unix())), +// Package: "prepay_id=" + res.Result, +// SignType: "RSA", +// PaySign: "", +// ThirdMsg: "", +// } +// +// // 4 签名 +// // 4.1 签名数据 +// signValue, err := task.Sign(response.AppId, response.TimeStamp, response.NonceStr, response.Package) +// if err != nil { +// utils.Log(nil, "签名失败", err) +// return response, errorcode.WechatAuthFail +// } +// response.PaySign = signValue +// +// return response, task.code +//}