问题1我纠结了好久,并没有找到合适解决方法,因为按照这个要求,操作由后台发起,由后台执行,而这样做,微信是不允许的,这也是为什么我会写一篇关于支付宝提现的帖子,但你去看支付宝的文档,会发现过程极其繁琐,还有时间差,而且微信与支付宝打架,这个功能还得放在微信外的页面,用户体验非常不好。
经过与老板的讨价还价,终于改变为了问题2 : 将发起者改为用户,这样以上的问题,就都不是问题了。
阅读代码之前墙裂建议先看完官方文档
业务场景:
用户点击页面上的按钮,post请求发送至后台,获取用户的id和要提现的金额,经过校验向用户微信钱包打款。
这就OK啦,用户的微信钱包是实时更新的。当然要是想再友好点,可以给用户发个消息,下一篇,就来写微信的客服功能。
本文来自:CSDN博客
感谢作者:u012210379
查看原文:使用golang快速开发微信公众平台(六):给用户发红包(用户提现至微信钱包)
查看原文:http://www.zoues.com/2016/10/27/%e4%bd%bf%e7%94%a8golang%e5%bf%ab%e9%80%9f%e5%bc%80%e5%8f%91%e5%be%ae%e4%bf%a1%e5%85%ac%e4%bc%97%e5%b9%b3%e5%8f%b0%e5%85%ad%e7%bb%99%e7%94%a8%e6%88%b7%e5%8f%91%e7%ba%a2%e5%8c%85%e7%94%a8%e6%88%b7/func (c *WXRedPacketController) Post() { uid,_ := c.GetSession("uid").(string) packegtMoney,err := c.GetFloat("packegtMoney",0) o := orm.NewOrm() if err == nil { //检查用户钱包内是否有这么多钱可供提现 uwallet := models.UserWallet{Uid:uid} if _,_,err := o.ReadOrCreate(&uwallet,"uid"); err == nil { umoney,_ := strconv.ParseFloat(uwallet.Money,64) if umoney >= packegtMoney { //提现至微信红包 str_req := makeRedPacketXML(packegtMoney,uid) if ok,errInfo := sendRedPacketRequest(str_req,uid); ok { uwallet.Money = strconv.FormatFloat(math.Floor((umoney - packegtMoney) * 100) / 100,21);">'f',2,64) _,175);">.Update(&uwallet,21);">"money") if err != nil { fmt.Println("用户提现更新钱包失败",err) logUtils.GetLog().Error(Box-sizing: border-Box; color: rgb(163,err) c.Data["errinfo"] = "更新钱包失败" } else { //插入 wallet-his _,err = o.Insert(&models.UserWalletHis{Uid:uid,MoneyChange:strconv.Floor(packegtMoney * 100) / 100,64),BonusChange:"0",ChangeReason:models.DRAW,BankType:"",BankNum:Box-sizing: border-Box; color: rgb(163,ReasonOrder:Box-sizing: border-Box; color: rgb(163,ReasonPerson:Box-sizing: border-Box; color: rgb(163,CreateTime:time.Now().Format(TIMELAYOUT),}) if err != nil { fmt.Printf("插入 UserWalletHis 错误 %v",err) logUtilsBox-sizing: border-Box; color: rgb(43,err) } } c.Redirect("/wx_red_packet",302) } else { c"errinfo"] = errInfo } } else { c"钱包余额不足" } } else { c"钱包查询错误" } } c"money"] = showWalletMoney(o,uid)//可提现 c.TplName = "wx_red_packget.html"} //生成红包的申请xml money 提现的金额 元 func makeRedPacketXML(money float64,uid string) string { //拼接xml var redPacket models.RedPacket redPacket.Nonce_str = RandomStrUtil.GetRandomString(32) redPacket.Mch_billno = beego.AppConfig.String("shopKey") + time.Format(TIMELAYOUT3) + strconv.FormatInt(time.Unix(),10) redPacket.Mch_id = beego"shopKey") redPacket.Appid = beego"APPID") redPacket.Send_name = "商城" redPacket.Re_openid = uid redPacket.Total_amount = int(money * 100)//分钱 redPacket.Total_num = 1 redPacket.Wishing = "收红包啦" redPacket.Client_ip = "122.122.122.122" redPacket.Act_name = "红包名称" redPacket.Remark = "红包说明" var n map[string]interface{} n = make(map[string]interface{},0) n["nonce_str"] = redPacket.Nonce_str n["mch_billno"] = redPacket.Mch_billno n["mch_id"] = redPacket.Mch_id n["wxappid"] = redPacket.Appid n["send_name"] = redPacket.Send_name n["re_openid"] = redPacket.Re_openid n["total_amount"] = redPacket.Total_amount n["total_num"] = redPacket.Total_num n["wishing"] = redPacket.Wishing n["client_ip"] = redPacket.Client_ip n["act_name"] = redPacket.Act_name n["remark"] = redPacket.Remark redPacket.Sign = wxpayCalcSign(n,PAY_API_KEY) //这个key 微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全 bytes_req,err := xml.Marshal(redPacket) if err != nil { fmt"转换为xml错误:",err) logUtilsBox-sizing: border-Box; color: rgb(43,err) } str_req := strings.Replace(string(bytes_req),21);">"RedPacket",21);">"xml",-1) fmt"发红包参数转换为xml--------",str_req) return str_req } func sendRedPacketRequest(str_req,uid string) (bool,string) { bytes_req := []byte(str_req) //发送unified order请求. req,err := http.NewRequest("POST",21);">"https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack",bytes.NewReader(bytes_req)) if err != nil { fmt"发送红包 Request发生错误,原因:",err) return false,21);">"未知错误" } req.Header.Set("Accept",21);">"application/xml") //这里的http header的设置是必须设置的. req"Content-Type",21);">"application/xml;charset=utf-8") tlsConfig,err := WxPlatUtil.GetTLSConfig() if err != nil { fmt"解析证书出现错误",21);">"未知错误" } tr := &http.Transport{TLSClientConfig: tlsConfig} client := &http.Client{Transport: tr} resp,_err := client.Do(req) if _err != nil { fmt"请求发送红包接口发送错误,原因:",_err) logUtils"未知错误" } respBytes,err := IoUtil.ReadAll(resp.Body) if err != nil { fmt"请求发送红包解析返回body错误",21);">"未知错误" } else { fmt"请求发送红包解析返回===================>",string(respBytes)) redPacketRes := models.RedPacketRes{} if err := xml.Unmarshal(respBytes,&redPacketRes); err == nil { recodeRedPacketRes(&redPacketRes,uid)//记录存入数据库 if redPacketRes.Return_code == "SUCCESS" { if redPacketRes.Result_code == "SUCCESS" { return true,21);">"红包领取成功" } else { return false,redPacketRes.Err_code_des } } else { //签名失败 return false,21);">"微信签名失败" } } else { fmt"红包领取记录解析错误",err) logUtils"未知错误"} func wxpayCalcSign(mReq map[string]interface{},key string) string { //fmt"========STEP 1,对key进行升序排序.========") //fmt"微信支付签名计算,API KEY:",key) //STEP 1,对key进行升序排序. sorted_keys := make([]string,0) for k,_ := range mReq { sorted_keys = append(sorted_keys,k) } sort.Strings(sorted_keys) //fmt"========STEP2,对key=value的键值对用&连接起来,略过空值========") //STEP2,对key=value的键值对用&连接起来,略过空值 var signStrings string for _,k := range sorted_keys { //fmt"k=%v,v=%v/n",k,mReq[k]) value := fmt.Sprintf("%v",mReq[k]) if value != "" { signStrings = signStrings + k + "=" + value + "&" } } //fmt"========STEP3,在键值对的最后加上key=API_KEY========") //STEP3,在键值对的最后加上key=API_KEY if key != "" { signStrings = signStrings + "key=" + key } //fmt"========STEP4,进行MD5签名并且将所有字符转为大写.========") //STEP4,进行MD5签名并且将所有字符转为大写. md5Ctx := md5.New() md5Ctx.Write([]byte(signStrings)) cipherStr := md5Ctx.Sum(nil) upperSign := strings.ToUpper(hex.EncodeToString(cipherStr)) return upperSign } func recodeRedPacketRes(redPacketRes *models.RedPacketRes,uid string) { //插入数据库 红包领取记录 o := orm.NewOrm() wxUser := models.WxUser{WxId:uid} if err := o.Read(&wxUser,21);">"wx_id"); err == nil { redPacketHis := models.RedPacketResHis{RedPacketRes:*redPacketRes,Name:wxUser.Name,Phone:wxUser.Phone,175);">.Format(TIMELAYOUT)} _,175);">.Insert(&redPacketHis) if err != nil { fmt"插入红包领取记录错误",21);">"红包领取记录",err) } } else { fmt"查询用户信息错误",err) } }
原文链接:https://www.f2er.com/go/189259.html