package pay import ( "encoding/json" "encoding/xml" "fmt" "log" "net/rpc" "time" util "app.yhyue.com/moapp/jybase/common" config "bp.jydev.jianyu360.cn/BaseService/payCenter/entity" ) const ( WX_REWARD_JSAPI = "a" //微信打赏 WX_DATAEXPORT_NATIVE = "b" //数据导出-扫码支付 WX_DATAEXPORT_JSAPI = "c" //数据导出-微信js支付 WX_DATAEXPORT_APP = "C" //数据导出-微信app支付 WX_DATAREPORT_JSAPI = "d" //数据报告-微信js支付 WX_DATAREPORT_APP = "D" //数据报告-微信app支付 WX_SUBVIP_JSAPI = "e" //VIP订阅-js支付 WX_SUBVIP_APP = "E" //VIP订阅-APP支付 WX_COURSE_JSAPI = "f" //剑鱼招投标课程-js支付 WX_COURSE_APP = "F" //剑鱼招投标课程-APP支付 WX_COURSE_NATIVE = "g" //剑鱼招投标课程-扫码支付 WX_ENTNICHE_APP = "H" //企业商机管理-APP支付 WX_COURSEONLINE_JSAPI = "i" //课程线上课程-js支付 WX_COURSEONLINE_APP = "I" //剑鱼线上课程-APP支付 WX_COURSEONLINE_NATIVE = "j" //剑鱼线上课程-扫码支付 WX_DATAREPORT_NATIVE = "k" //数据报告-扫码支付 WX_SUBVIP_NATIVE = "l" //VIP订阅-扫码支付 WX_ENTNICHE_NATIVE = "m" //商机管理-pc支付 WX_MEMBER_JSAPI = "n" //大会员-微信js支付 WX_MEMBER_APP = "N" //大会员-APP支付 WX_MEMBER_NATIVE = "o" //大会员-PC支付 WX_AIFORECASTPACK_JSAPI = "P" //大会员-AI中标预测包-微信js支付 WX_AIFORECASTPACK_APP = "p" //大会员-AI中标预测包-APP支付 WX_AIFORECASTPACK_NATIVE = "q" //大会员-AI中标预测包-PC支付 WX_BIDFILE_JSAPI = "R" //招标文件解读-微信js支付 WX_BIDFILE_APP = "r" //招标文件解读-APP支付 WX_BIDFILE_NATIVE = "S" //招标文件解读-PC支付 WX_INTEGRAL_JSAPI = "AA" //剑鱼币-微信js支付 WX_INTEGRAL_APP = "AB" //剑鱼币-APP支付 WX_INTEGRAL_NATIVE = "AC" //剑鱼币-PC支付 /*新命名规范 A 「ali阿里支付宝支付」 W 「wx微信支付」 A 「app支付」 J「js支付*仅微信端有」 P「pc扫码支付」 P 「产品标识」 pack 数据包 */ WX_DATAPACK_JSAIP = "WJP" //数据包-微信js支付 WX_DATAPACK_APP = "WAP" //数据包-app支付 WX_DATAPACK_NATIVE = "WPP" //数据包-pc支付 WX_AREAPACK_JSAPI = "WJA" //省份订阅包 微信js支付 WX_AREAPACK_APP = "WAA" //省份订阅包 app微信支付 WX_AREAPACK_NATIVE = "WPA" //省份订阅包 微信pc支付 WX_FILEPACK_JSAPI = "WJF" //附件下载包 微信js支付 WX_FILEPACK_APP = "WAF" //附件下载包 app微信支付 WX_FILEPACK_NATIVE = "WPF" //附件下载包 微信pc支付 WX_BUYERPORTRAITPACK_JSAPI = "WJB" //采购单位画像包 微信js支付 WX_BUYERPORTRAITPACK_APP = "WAB" //采购单位画像包 app微信支付 WX_BUYERPORTRAITPACK_NATIVE = "WPB" //采购单位画像包 微信pc支付 ) var WxStruct *WeixinStruct type WeixinStruct struct { Appid string Mchid string Appid_app string //微信支付和app支付appid不一致 Key string Dashang_attachmsg string Dashang_bodymsg string Dashang_detailmsg string sjdc_msg string Sjbg_msg string Subvip_msg string Entniche_msg string Course_msg string CourseOnline_msg string Member_msg string Aiforecastpage_msg string Bidfile_msg string OpenidSwitch *map[string]interface{} Integral_msg string DataPack_msg string AreaPack_msg string FilePack_msg string BuyerPortraitPack_msg string } func init() { //payConfig := config.WxPayConf["pay"].(map[string]interface{}) // //WxStruct = &WeixinStruct{ // Appid: util.ObjToString(config.WxPayConf["appid"]), // Appid_app: util.ObjToString(config.WxPayConf["appid_app"]), // Mchid: util.ObjToString(payConfig["mchid"]), // Key: util.ObjToString(payConfig["key"]), // Dashang_attachmsg: util.ObjToString(payConfig["attachmsg"]), // Dashang_bodymsg: util.ObjToString(payConfig["bodymsg"]), // Dashang_detailmsg: util.ObjToString(payConfig["detailmsg"]), // sjdc_msg: util.ObjToString(payConfig["sjdc_msg"]), // Sjbg_msg: util.ObjToString(payConfig["sjbg_msg"]), // Subvip_msg: util.ObjToString(payConfig["subvip_msg"]), // Entniche_msg: util.ObjToString(payConfig["entniche_msg"]), // Course_msg: util.ObjToString(payConfig["course_msg"]), // CourseOnline_msg: util.ObjToString(payConfig["courseOnline_msg"]), // Member_msg: util.ObjToString(payConfig["member_msg"]), // Aiforecastpage_msg: util.ObjToString(payConfig["aiforecastpage_msg"]), // Bidfile_msg: util.ObjToString(payConfig["bidfile_msg"]), // OpenidSwitch: util.ObjToMap(config.WxPayConf["openidSwitch"]), // Integral_msg: util.ObjToString(payConfig["integral_msg"]), // DataPack_msg: util.ObjToString(payConfig["dataPack_msg"]), // AreaPack_msg: util.ObjToString(payConfig["areaPack_msg"]), // FilePack_msg: util.ObjToString(payConfig["filePack_msg"]), // BuyerPortraitPack_msg: util.ObjToString(payConfig["buyerPortraitPack_msg"]), //} } func (w *WeixinStruct) GetTradeno(tp string) string { lenRandom := 6 - len([]rune(tp)) //控制长度 tradeno := fmt.Sprintf("%s_%d%s%s", tp, time.Now().UnixNano(), util.GetRandom(lenRandom), util.GetLetterRandom(6)) tradeno = processTradeno(tradeno) return tradeno } //tradeno a:打赏 b:pc端数据导出 c:移动端微信数据导出 C:app数据导出 d:微信端数据报告 D:app端数据报告 func (w *WeixinStruct) CreatePrepayOrder(tradeno, ip, openid, detailmsg string, totalfee int) (string, *map[string]string) { defer util.Catch() //测试环境,1分钱 // if config.Config.AllPayMoney > 0 { // totalfee = config.Config.AllPayMoney // } notifyUrl := util.ObjToString(config.PayConf["webdomain"]) + "/jypay/callback/wxPay" //获取支付标题 attachmsg, bodymsg := "", "" if tradeno == WX_REWARD_JSAPI { //打赏 attachmsg, bodymsg = w.Dashang_attachmsg, w.Dashang_bodymsg } else if tradeno == WX_DATAEXPORT_NATIVE || tradeno == WX_DATAEXPORT_JSAPI || tradeno == WX_DATAEXPORT_APP { //数据导出 attachmsg, bodymsg, detailmsg = w.sjdc_msg, w.sjdc_msg, w.sjdc_msg } else if tradeno == WX_DATAREPORT_JSAPI || tradeno == WX_DATAREPORT_APP || tradeno == WX_DATAREPORT_NATIVE { //数据报告 attachmsg, bodymsg, detailmsg = w.Sjbg_msg, w.Sjbg_msg, w.Sjbg_msg } else if tradeno == WX_SUBVIP_JSAPI || tradeno == WX_SUBVIP_APP || tradeno == WX_SUBVIP_NATIVE { //vip订阅 attachmsg, bodymsg, detailmsg = w.Subvip_msg, w.Subvip_msg, w.Subvip_msg } else if tradeno == WX_COURSE_NATIVE || tradeno == WX_COURSE_APP || tradeno == WX_COURSE_JSAPI { //招投标课程 attachmsg, bodymsg, detailmsg = w.Course_msg, w.Course_msg, w.Course_msg } else if tradeno == WX_ENTNICHE_APP || tradeno == WX_ENTNICHE_NATIVE { attachmsg, bodymsg, detailmsg = w.Entniche_msg, w.Entniche_msg, w.Entniche_msg } else if tradeno == WX_COURSEONLINE_APP || tradeno == WX_COURSEONLINE_JSAPI || tradeno == WX_COURSEONLINE_NATIVE { attachmsg, bodymsg, detailmsg = w.CourseOnline_msg, w.CourseOnline_msg, w.CourseOnline_msg } else if tradeno == WX_MEMBER_NATIVE || tradeno == WX_MEMBER_APP || tradeno == WX_MEMBER_JSAPI { attachmsg, bodymsg, detailmsg = w.Member_msg, w.Member_msg, w.Member_msg } else if tradeno == WX_AIFORECASTPACK_APP || tradeno == WX_AIFORECASTPACK_JSAPI || tradeno == WX_AIFORECASTPACK_NATIVE { attachmsg, bodymsg, detailmsg = w.Aiforecastpage_msg, w.Aiforecastpage_msg, w.Aiforecastpage_msg } else if tradeno == WX_BIDFILE_APP || tradeno == WX_BIDFILE_JSAPI || tradeno == WX_BIDFILE_NATIVE { attachmsg, bodymsg, detailmsg = w.Bidfile_msg, w.Bidfile_msg, w.Bidfile_msg } else if tradeno == WX_INTEGRAL_APP || tradeno == WX_INTEGRAL_JSAPI || tradeno == WX_INTEGRAL_NATIVE { attachmsg, bodymsg, detailmsg = w.Integral_msg, w.Integral_msg, w.Integral_msg } else if tradeno == WX_DATAPACK_APP || tradeno == WX_DATAPACK_JSAIP || tradeno == WX_DATAPACK_NATIVE { attachmsg, bodymsg, detailmsg = w.DataPack_msg, w.DataPack_msg, w.DataPack_msg } else if tradeno == WX_AREAPACK_APP || tradeno == WX_AREAPACK_JSAPI || tradeno == WX_AREAPACK_NATIVE { attachmsg, bodymsg, detailmsg = w.AreaPack_msg, w.AreaPack_msg, w.AreaPack_msg } else if tradeno == WX_FILEPACK_APP || tradeno == WX_FILEPACK_JSAPI || tradeno == WX_FILEPACK_NATIVE { attachmsg, bodymsg, detailmsg = w.FilePack_msg, w.FilePack_msg, w.FilePack_msg } else if tradeno == WX_BUYERPORTRAITPACK_APP || tradeno == WX_BUYERPORTRAITPACK_JSAPI || tradeno == WX_BUYERPORTRAITPACK_NATIVE { attachmsg, bodymsg, detailmsg = w.BuyerPortraitPack_msg, w.BuyerPortraitPack_msg, w.BuyerPortraitPack_msg } //支付类型分类 tradeType, appid := "", w.Appid if tradeno == WX_REWARD_JSAPI || tradeno == WX_DATAEXPORT_JSAPI || tradeno == WX_DATAREPORT_JSAPI || tradeno == WX_SUBVIP_JSAPI || tradeno == WX_COURSE_JSAPI || tradeno == WX_COURSEONLINE_JSAPI || tradeno == WX_MEMBER_JSAPI || tradeno == WX_AIFORECASTPACK_JSAPI || tradeno == WX_BIDFILE_JSAPI || tradeno == WX_INTEGRAL_JSAPI || tradeno == WX_DATAPACK_JSAIP || tradeno == WX_AREAPACK_JSAPI || tradeno == WX_FILEPACK_JSAPI || tradeno == WX_BUYERPORTRAITPACK_JSAPI { //微信js支付 tradeType = "JSAPI" } else if tradeno == WX_DATAEXPORT_APP || tradeno == WX_DATAREPORT_APP || tradeno == WX_SUBVIP_APP || tradeno == WX_COURSE_APP || tradeno == WX_ENTNICHE_APP || tradeno == WX_COURSEONLINE_APP || tradeno == WX_MEMBER_APP || tradeno == WX_AIFORECASTPACK_APP || tradeno == WX_BIDFILE_APP || tradeno == WX_INTEGRAL_APP || tradeno == WX_DATAPACK_APP || tradeno == WX_AREAPACK_APP || tradeno == WX_FILEPACK_APP || tradeno == WX_BUYERPORTRAITPACK_APP { //app支付 tradeType = "APP" appid = w.Appid_app } else if tradeno == WX_DATAEXPORT_NATIVE || tradeno == WX_COURSE_NATIVE || tradeno == WX_COURSEONLINE_NATIVE || tradeno == WX_DATAREPORT_NATIVE || tradeno == WX_ENTNICHE_NATIVE || tradeno == WX_SUBVIP_NATIVE || tradeno == WX_MEMBER_NATIVE || tradeno == WX_AIFORECASTPACK_NATIVE || tradeno == WX_BIDFILE_NATIVE || tradeno == WX_INTEGRAL_NATIVE || tradeno == WX_DATAPACK_NATIVE || tradeno == WX_AREAPACK_NATIVE || tradeno == WX_FILEPACK_NATIVE || tradeno == WX_BUYERPORTRAITPACK_NATIVE { //扫码支付 tradeType = "NATIVE" } tradeno = w.GetTradeno(tradeno) //测试环境微信支付需要转换对应的正式环境的openid if w.OpenidSwitch != nil { if oid, ok := (*(w.OpenidSwitch))[openid]; ok { openid = oid.(string) } } //获取预订单号 ret, _ := w.GetPrepayId(util.ObjToString(config.PayConf["weixinrpc"]), map[string]string{ "attachmsg": attachmsg, "bodymsg": bodymsg, "detailmsg": detailmsg, "useropenid": openid, "tradeno": tradeno, "userip": ip, "totalfee": fmt.Sprint(totalfee), "mchid": w.Mchid, "key": w.Key, "notifyUrl": notifyUrl, "appid": appid, "tradeType": tradeType, //NATIVE JSAPI APP }) return tradeno, ret } //取得预生成订单编号,我们的系统要控制下,别订单重复了 func (w *WeixinStruct) GetPrepayId(weixinrpc string, param map[string]string) (res *map[string]string, e error) { util.Try(func() { client, err := rpc.DialHTTP("tcp", weixinrpc) defer client.Close() if err != nil { e = err log.Println(err.Error()) return } var ret []byte err = client.Call("WeiXinRpc.GetPrepayId", param, &ret) if err != nil { e = err log.Println(err.Error()) } else { json.Unmarshal(ret, &res) } }, func(e interface{}) {}) return } //微信支付订单关闭 func (w *WeixinStruct) CloseOrder(tradeno, payWay string) (r bool) { util.Try(func() { client, err := rpc.DialHTTP("tcp", util.ObjToString(config.PayConf["weixinrpc"])) defer client.Close() if err != nil { return } err = client.Call("WeiXinRpc.CloseOrder", map[string]string{ "tradeno": tradeno, "key": w.Key, "mchid": w.Mchid, "appid": w.Appid, }, &r) if err != nil { log.Println(err.Error()) return } }, func(e interface{}) {}) return r } //微信js支付获取支付参数 func (w *WeixinStruct) GetWxjsPaySign(prepayid string) string { timestamp := time.Now().Unix() nonceStr := util.GetRandom(16) + util.GetLetterRandom(16) sign := util.WxSign(fmt.Sprintf("appId=%s&nonceStr=%s&package=%s&signType=%s&timeStamp=%d&key=%s", w.Appid, nonceStr, "prepay_id="+prepayid, "MD5", timestamp, w.Key)) res := map[string]interface{}{ "appId": w.Appid, "timestamp": fmt.Sprint(timestamp), "signType": "MD5", "sign": sign, "nonceStr": nonceStr, "prepayId": "prepay_id=" + prepayid, } byteArr, _ := json.Marshal(res) return string(byteArr) } //微信app支付 获取支付串 func (wx *WeixinStruct) GetAppWxPayStr(prepayid string) string { data := struct { XMLName xml.Name `xml:"xml"` Appid string `xml:"appid"` Partnerid string `xml:"partnerid"` //微信支付分配的商户号 Prepayid string `xml:"prepayid"` //微信返回的支付交易会话ID PackageStr string `xml:"package"` //暂填写固定值Sign=WXPay Noncestr string `xml:"noncestr"` //随机字符串,不长于32位。 Timestamp string `xml:"timestamp"` //时间戳 Sign string `xml:"sign"` //签名 }{ Appid: wx.Appid_app, Partnerid: wx.Mchid, Prepayid: prepayid, PackageStr: "Sign=WXPay", Noncestr: util.GetRandom(16) + util.GetLetterRandom(16), Timestamp: fmt.Sprintf("%d", time.Now().Unix()), } data.Sign = util.CreateWxSign(fmt.Sprintf("&key=%s", wx.Key), data) byteArr, err := json.Marshal(data) if err != nil { log.Printf("CreatePrepayOrder Marshal %v\n", err) return "" } return string(byteArr) } //获取js支付参数(为方便存库返回string,前端需要转成json) func GetWxJsPayStr(prepayid string) string { //获取订单支付字符串 nonceStr := util.GetRandom(16) + util.GetLetterRandom(16) timestamp := time.Now().Unix() sign := util.WxSign(fmt.Sprintf("appId=%s&nonceStr=%s&package=%s&signType=%s&timeStamp=%d&key=%s", WxStruct.Appid, nonceStr, "prepay_id="+prepayid, "MD5", timestamp, WxStruct.Key)) m := map[string]interface{}{ "appId": WxStruct.Appid, "timestamp": fmt.Sprint(timestamp), "signType": "MD5", "sign": sign, "nonceStr": nonceStr, "prepayId": "prepay_id=" + prepayid, } byteArr, err := json.Marshal(m) if err != nil { log.Println("GetWxJsPayStr ", err) return "" } return string(byteArr) }