|
|
@@ -0,0 +1,112 @@
|
|
|
+package server
|
|
|
+
|
|
|
+import (
|
|
|
+ "context"
|
|
|
+ "fmt"
|
|
|
+ "github.com/go-pay/gopay"
|
|
|
+ "github.com/go-pay/gopay/wechat"
|
|
|
+ "github.com/shopspring/decimal"
|
|
|
+ "github.com/spf13/viper"
|
|
|
+ "go_zh/pkg/utils"
|
|
|
+ "strconv"
|
|
|
+ "sync"
|
|
|
+ "time"
|
|
|
+)
|
|
|
+
|
|
|
+type WeChatV2Server struct {
|
|
|
+ MchId string
|
|
|
+ PrivateKey string
|
|
|
+ CertFile string //公钥证书地址
|
|
|
+ PrivateKeyFile string //私钥证书地址
|
|
|
+ AppId string //appid
|
|
|
+ AppSecret string
|
|
|
+ AppletId string
|
|
|
+ AppletKey string
|
|
|
+ PublicKeyInfo string
|
|
|
+ PrivateKeyFileInfo string
|
|
|
+}
|
|
|
+
|
|
|
+var (
|
|
|
+ weChatV2ServerInstance *WeChatV2Server
|
|
|
+ weChatV2ServerOnce sync.Once
|
|
|
+)
|
|
|
+
|
|
|
+// GetWeChatV2ServerInstance 获取单例实例
|
|
|
+func GetWeChatV2ServerInstance() *WeChatV2Server {
|
|
|
+ weChatV2ServerOnce.Do(func() {
|
|
|
+ weChatV2ServerInstance = &WeChatV2Server{
|
|
|
+ MchId: viper.GetString("weChat.mchId"),
|
|
|
+ PrivateKey: viper.GetString("weChat.privateKey"),
|
|
|
+ CertFile: viper.GetString("weChat.certFile"),
|
|
|
+ PrivateKeyFile: viper.GetString("weChat.keyFile"),
|
|
|
+ AppId: viper.GetString("weChat.appId"),
|
|
|
+ AppSecret: viper.GetString("weChat.appSecret"),
|
|
|
+ AppletId: viper.GetString("weChat.appletId"),
|
|
|
+ AppletKey: viper.GetString("weChat.appletKey"),
|
|
|
+ }
|
|
|
+ weChatPublicKeyStr := utils.LoadPublicKeyWithPath(weChatV2ServerInstance.CertFile)
|
|
|
+ weChatV2ServerInstance.PublicKeyInfo = weChatPublicKeyStr
|
|
|
+
|
|
|
+ weChatPrivateKeyStr := utils.LoadPrivateKeyWithPath(weChatV2ServerInstance.PrivateKeyFile)
|
|
|
+ weChatV2ServerInstance.PrivateKeyFileInfo = weChatPrivateKeyStr
|
|
|
+ })
|
|
|
+ return weChatV2ServerInstance
|
|
|
+}
|
|
|
+
|
|
|
+type JsApiV2Data struct {
|
|
|
+ AppId string `json:"appId"` //员工ID
|
|
|
+ NonceStr string `json:"nonceStr"` //当前登录token
|
|
|
+ Package string `json:"package"` //当前登录token
|
|
|
+ SignType string `json:"signType"` //当前登录token
|
|
|
+ TimeStamp string `json:"timeStamp"` //当前登录token
|
|
|
+ PaySign string `json:"paySign"` //当前登录token
|
|
|
+}
|
|
|
+
|
|
|
+// WeChatV2JsPay 获取
|
|
|
+func (weChatV2 *WeChatV2Server) WeChatV2JsPay(orderSn string, payMoney decimal.Decimal, notifyUrl string, boby string, openId string, clientIP string) JsApiV2Data {
|
|
|
+ // 初始化微信客户端
|
|
|
+ // appId:应用ID
|
|
|
+ // mchId:商户ID
|
|
|
+ // apiKey:API秘钥值
|
|
|
+ // isProd:是否是正式环境
|
|
|
+ client := wechat.NewClient(weChatV2.AppId, weChatV2.MchId, weChatV2.PrivateKey, true)
|
|
|
+
|
|
|
+ bm := make(gopay.BodyMap)
|
|
|
+ bm.Set("nonce_str", utils.Md5Sign(orderSn)).
|
|
|
+ Set("spbill_create_ip", clientIP).
|
|
|
+ Set("appid", weChatV2.AppId).
|
|
|
+ Set("mch_id", weChatV2.MchId).
|
|
|
+ Set("body", boby).
|
|
|
+ Set("out_trade_no", orderSn).
|
|
|
+ Set("notify_url", notifyUrl).
|
|
|
+ Set("trade_type", "JSAPI").
|
|
|
+ Set("total_fee", payMoney.Mul(decimal.NewFromInt(100)).IntPart()).
|
|
|
+ Set("openid", openId)
|
|
|
+
|
|
|
+ wxRsp, err := client.UnifiedOrder(context.Background(), bm)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("err:", err)
|
|
|
+ }
|
|
|
+ // ====微信小程序 paySign====
|
|
|
+ timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
|
|
|
+ packages := "prepay_id=" + wxRsp.PrepayId // 此处的 wxRsp.PrepayId ,统一下单成功后得到
|
|
|
+ // 获取微信小程序支付的 paySign
|
|
|
+ // appId:AppID
|
|
|
+ // nonceStr:随机字符串
|
|
|
+ // packages:统一下单成功后拼接得到的值
|
|
|
+ // signType:签名方式,务必与统一下单时用的签名方式一致
|
|
|
+ // timeStamp:时间
|
|
|
+ // apiKey:API秘钥值
|
|
|
+ paySign := wechat.GetMiniPaySign(weChatV2.AppId, wxRsp.NonceStr, packages, wechat.SignType_MD5, timeStamp, weChatV2.PrivateKey)
|
|
|
+
|
|
|
+ data := JsApiV2Data{
|
|
|
+ AppId: weChatV2.AppId,
|
|
|
+ NonceStr: utils.Md5Sign(timeStamp),
|
|
|
+ Package: "prepay_id=" + wxRsp.PrepayId,
|
|
|
+ SignType: "MD5",
|
|
|
+ TimeStamp: timeStamp,
|
|
|
+ PaySign: paySign,
|
|
|
+ }
|
|
|
+
|
|
|
+ return data
|
|
|
+}
|