C# MVC 微信支付之小程序红包

news2024/12/28 5:52:54

       最近有个项目增加导游引流功能,因为项目只用的小程序,没有使用公众号,没法用”现金红包“功能,开通商家转账到零钱需要7-14天才能申请下来,暂时先用小程序红包顶上,一路都是坑啊,特此记录下。

        官方文档【微信支付】小程序红包开发者文档 (qq.com)

先开下具体效果,点击领取佣金=>生成红包=>领取红包

废话不多说,开始走起

1、开通(省略)

2、向运营账户中充值(开始以为可以用账户金额了,自己想多了,说明微信想的多么周到)

3、以用户OpenID为基础生成一个红包,然后在前端直接领取, 所以有两个流程   一个是生成红包,一个是领取红包。

4、具体实现(根据实际情况进行设计,我们的项目是凌晨对前一天的订单进行结算,结算完导游就能进行领取了,我这里是前端小程序进行的生成和领取的,这个要根据实际业务来设计)

5、部分代码(.net core)

生成红包

[HttpPost]
        public async Task<ActionResult> SendMiniProgramhb(string openid,string billno,decimal amount)
        {
            try
            {
                string url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendminiprogramhb";

                string nonce_str = WXPay.GetNoncestr();
                string total_amount = (Math.Round((decimal)amount * 100, 0)).ToString();
                //参与统一下单签名的参数,除最后的key外,已经按参数名ASCII码从小到大排序
                string unifiedorderSignParam = string.Format("act_name={0}&mch_billno={1}&mch_id={2}&nonce_str={3}&notify_way={4}&re_openid={5}&remark={6}&send_name={7}&total_amount={8}&total_num={9}&wishing={10}&wxappid={11}&key={12}"
                    , "导游分佣", billno, MCH_ID, nonce_str, "MINI_PROGRAM_JSAPI",openid, "导游分佣", "xxx", total_amount,"1", "感谢您的付出!",APP_ID, KEY);
                //MD5加密并将结果转换成大写
                string unifiedorderSign =WXPay.GetMD5(unifiedorderSignParam).ToUpper();

                //获取统一的下单的请求参数
                string param = string.Format(@"<xml>
                                                <act_name>导游分佣</act_name>
                                                <mch_billno>{0}</mch_billno>
                                                <mch_id>{1}</mch_id>
                                                <nonce_str>{2}</nonce_str>
                                                <notify_way>MINI_PROGRAM_JSAPI</notify_way>
                                                <re_openid>{3}</re_openid>
                                                <remark>导游分佣</remark>
                                                <send_name>xxx</send_name>
                                                <total_amount>{4}</total_amount>
                                                <total_num>1</total_num>
                                                <wishing>感谢您的付出!</wishing>
                                                <wxappid>{5}</wxappid>
                                                <sign>{6}</sign>
                                               </xml>", billno, MCH_ID, nonce_str,openid, total_amount,APP_ID, unifiedorderSign); ;


                string ret = WxRedPackPost(url, param);
                var payRes = XDocument.Parse(ret);
                var root = payRes.Element("xml");
                //序列化相应参数返回给小程序
                var res = GetPayRequestParam(root);
                if(res  == null)
                {
                    return Json(new TData<PayRequesEntity> { Tag = 0, Message="生成红包有误!" });
                }
                else
                {
                    return Json(new TData<PayRequesEntity> { Tag = 1, Data = res });
                }
                
               
            }
            catch (Exception ex)
            {

                return Json(new TData { Tag = 0, Message = ex.Message });
            }
        }

这个要注意,红包功能需要证书

public string WxRedPackPost(string posturl, string postData)
{
    Stream outstream = null;
    Stream instream = null;
    StreamReader sr = null;
    HttpWebResponse response = null;
    HttpWebRequest request = null;
    Encoding encoding = Encoding.UTF8;
    byte[] data = encoding.GetBytes(postData);
    // 准备请求...  
    try
    {
        //CerPath证书路径,这里是本机的路径,实际应用中,按照实际情况来填写
        string certPath = GlobalContext.WxConfig.SSLCERT_PATH;
        //证书密码
        string password = GlobalContext.WxConfig.SSLCERT_PASSWORD;
        X509Certificate2 cert = new System.Security.Cryptography.X509Certificates.X509Certificate2(certPath, password, X509KeyStorageFlags.MachineKeySet);

        // 设置参数  
        request = WebRequest.Create(posturl) as HttpWebRequest;
        CookieContainer cookieContainer = new CookieContainer();
        request.CookieContainer = cookieContainer;//不可少(个人理解为,返回的时候需要验证)
        request.AllowAutoRedirect = true;
        request.Method = "POST";
        request.ContentType = "text/xml";
        request.ContentLength = data.Length;
        request.ClientCertificates.Add(cert);//添加证书请求
        outstream = request.GetRequestStream();
        outstream.Write(data, 0, data.Length);
        outstream.Close();
        //发送请求并获取相应回应数据  
        response = request.GetResponse() as HttpWebResponse;
        //直到request.GetResponse()程序才开始向目标网页发送Post请求  
        instream = response.GetResponseStream();
        sr = new StreamReader(instream, encoding);
        //返回结果网页(html)代码  
        string content = sr.ReadToEnd();
        string err = string.Empty;
        return content;

    }
    catch (Exception ex)
    {
        string err = ex.Message;
        return string.Empty;
    }
}

paySign签名生成这里容易犯错

a 参与签名的字段包括:appId、nonceStr、package、timeStamp,就这四个,不要用之前经验来弄,

b 不用转成大写,转成大写就会签名错误。

c 返回前端的package要进行urlencode。

        private static PayRequesEntity GetPayRequestParam(XElement root)
        {
            //当return_code 和result_code都为SUCCESS时才有我们要的prepay_id
            if (root.Element("return_code").Value == "SUCCESS" && root.Element("result_code").Value == "SUCCESS")
            {
                if (root.Element("return_msg").Value == "发放成功")
                {

                    var package = root.Element("package").Value;//统一下单接口返回的 prepay_id 参数值
                    var nonceStr = WXPay.GetNoncestr();//获取随机字符串
                    var signType = "MD5";//加密方式
                    var timeStamp = Convert.ToInt64((DateTime.Now - new DateTime(1970, 1, 1)).TotalSeconds).ToString();//时间戳

                    var paySignParam = string.Format("appId={0}&nonceStr={1}&package={2}&timeStamp={3}&key={4}",
                          APP_ID, nonceStr, HttpUtility.UrlEncode(package), timeStamp, KEY);
                    //二次加签
                    var paySign = WXPay.GetMD5(paySignParam);

                    PayRequesEntity payEntity = new PayRequesEntity
                    {
                        package = HttpUtility.UrlEncode(package),
                        nonceStr = nonceStr,
                        paySign = paySign,
                        signType = signType,
                        timeStamp = timeStamp
                    };
                    return payEntity;
                }
            }

            return null;
        }

此方法又增加了一个“return_msg”的判断,因为出现了这种情况,正常情况下面领取红包后进行状态修改,发现如果再领取完页面不返回是不走领取成功事件,也就出现了领取了但是状态没有改变,再次领取的时候就会返回这样的数据(下面xml),所以只用“SUCCESS”判断没法友好提醒,所以加了这个逻辑,如果有好办法,大伙告诉我哦!

<xml>
  <return_code><![CDATA[SUCCESS]]></return_code>
  <return_msg><![CDATA[该红包已经成功,已经被领取或者发起退款]]></return_msg>
  <result_code><![CDATA[SUCCESS]]></result_code>
  <err_code><![CDATA[SUCCESS]]></err_code>
  <err_code_des><![CDATA[该红包已经成功,已经被领取或者发起退款]]></err_code_des>
  <mch_billno><![CDATA[]]></mch_billno>
  <mch_id><![CDATA[]]></mch_id>
  <wxappid><![CDATA[]]></wxappid>
  <re_openid><![CDATA[]]></re_openid>
  <total_amount>100</total_amount>
</xml>

前端微信小程序

这个要注意就是场景只支持1011、1025、1047和1124,只能用摄像头扫,长按是不行的。

getUserHongbao(e) {
    const _this = this
    let user_id = ''
    wx.login({
      success: function (res) {
        console.log('wxlogin code:' + res.code);
        codeWx({
            code: res.code
          })
          .then(res => {
            wx.setStorageSync('openId', res.Data.openid)
            _this.setData({
              openId: res.Data.openid
            })
            var sceneCode = wx.getLaunchOptionsSync() //获取场景代码
            if (sceneCode.scene == 1047 || sceneCode.scene == 1011 || sceneCode.scene == 1025 || sceneCode.scene == 1124) {
            }
            else
            {
              wxShowToast('领取方式有误,请联系工作人员。', 'none', 4000);
              return;
            }
            //检测是否有提现金额
            wx.request({
              url: baseUrl + '***/GetFormJsonByOpenId?openid=' + _this.data.openId,
              method: "POST",
              success(res) {
                if (res.data.Tag == 1) {
                  //创建红包
                  wx.request({
                    url: baseUrl + '***/GenMiniProgramhb?openid=' + _this.data.openId,
                    method: "POST",
                    success(res) {
                      if (res.data.Tag == 0) {
                        wxShowToast(res.data.Message, 'none', 4000);
                      } else {
                        var orderid = res.data.Data.OrderCode
                        //领取红包
                        //1011 扫描二维码 1025 扫描一维码 1047 扫描小程序码 1124 扫“一物一码”打开小程序                        
                          //领取红包的代码
                          wx.sendBizRedPacket({
                            "timeStamp": res.data.Data.timeStamp, // 支付签名时间戳,
                            "nonceStr": res.data.Data.nonceStr, // 支付签名随机串,不长于 32 位
                            "package": res.data.Data.package, //扩展字段,由商户传入
                            "signType": res.data.Data.signType, // 签名方式,
                            "paySign": res.data.Data.paySign, // 支付签名
                            "success": function (res) {
                              console.log("success:");
                              console.log(res);
                              wx.request({
                                url: baseUrl + '***/MiniProgramhbC?id=' + orderid,
                                method: "POST",
                                success(res) {
                                  console.log(res);
                                }
                              })
                            },
                            "fail": function (res) {
                              console.log("fail:");
                              console.log(res);
                            },
                            "complete": function (res) {
                              console.log("complete:");
                              console.log(res);
                            }
                          })                        
                      }
                    }
                  })
                } else {
                  wxShowToast(res.data.Message, 'none', 4000);
                }
              }
            })
          })
      },
      fail: function () {
        console.info("1授权失败返回数据");
        wx.hideLoading()
        wx.showModal({
          title: '提示',
          content: '请重新授权哦'
        })
        return;
      }
    })
  },

到这就结束了,请大家指教。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/560034.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

docker常规命令使用

docker 操作 命令分类 启动类、镜像、容器 docker服务启动 systemctl start docker docker 版本查看 docker version 列出本机所有镜像 docker images 在远程仓库中查找镜像 docker search --limit 5 redis //从仓库中查找点赞数前5的redis镜像 从远程仓库中拉取镜像 docker …

Wireshark - 过滤表达式的规则

文章目录 1. 过滤 协议2. 过滤 端口3. 过滤 IP4. 过滤 TCP重传数据包5. 包长度过滤6. <未完待续2023.5.23> 1. 过滤 协议 1、TCP - 只显示TCP协议2、!TCP - 排除TCP协议 2. 过滤 端口 1、tcp.port6666 - 显示&#xff08;不分来源或目标&#xff09;端口2、tcp.dstp…

Hadoop完全分布式搭建

主机设置 三台主机关闭防火墙 三台主机关闭SeLinux安全机制 给每台主机修改主机名 配置三台主机地址映射 设置免密登录 安装JDK 解压安装 配置jdk的环境变量 测试安装成功 分发JDK 安装配置 Hadoop 解压安装 Hadoop环境配置文件 - hadoop-env.sh 修改Hadoop…

【电商必备】增长销售和客户在线支持的网站即时聊天(一)

科技的进步无疑令商业世界更加国际化&#xff0c;你的公司一定有来自世界各地的客户。试想一下&#xff0c;你的公司本部在亚洲&#xff0c;但有国外的客户在非工作时间透过Google搜寻到你公司&#xff0c;并有疑问期望实时得到回复&#xff0c;我们可以如何解决时差的问题呢&a…

MySQL 事务篇

事务有哪些特性&#xff1f; 原子性&#xff1a; 一个事务中的所有操作&#xff0c;必须全部执行。要么全部完成要么就不完成。中间如果出现错误&#xff0c;就要回滚到初始状态。 持久性&#xff1a; 事务处理结束后&#xff0c;对数据的修改就是永久的&#xff0c;就是系统故…

使用CSS来实现爱心信封的效果

想必在520大家都和女朋友过了完美的节日&#xff0c;可是博主还没有女朋友鹅鹅鹅&#xff0c;还是写一个爱心信封来维护自己弱小的心灵吧鹅鹅鹅 个人名片&#xff1a; &#x1f60a;作者简介&#xff1a;一名大一在校生&#xff0c;web前端开发专业 &#x1f921; 个人主页&a…

用友助力中核集团建设财务共享中心新华发电分中心,实现业财融合

企业在进行决策时需要大量的财务信息作为依据&#xff0c;财务共享中心的建设可以帮助企业将财务和业务分离后重新有序融合&#xff0c;使得决策数据更有价值&#xff0c;也帮助企业的管理和决策更加贴合实际。 新华水力发电有限公司&#xff08;简称“新华发电”&#xff09;…

IPEmotion采集J1939协议信号

一 背景 由于商用车相对于乘用车更注重实用性&#xff0c;功能也较单一&#xff0c;且具有产量小的特点&#xff0c;因此在设计开发时需要进行约束&#xff0c;以更大程度实现软硬件的复用和成本的降低&#xff0c;在此需求下J1939协议便随之产生了。 J1939协议是由美国汽车工…

使用Fiddler工具抓取微信小程序中的图片,使用Fiddler工具抓取电脑访问的链接图片

背景&#xff1a; 开发微信小程序的时候&#xff0c;是不是经常看到别人的小程序中某个图标或者图片好看想用&#xff0c;下面小编给大家分享一下怎么获得微信小程序中的图片。 一.什么是Fiddler 官网&#xff1a;https://www.telerik.com/ 下载地址1&#xff1a;Fiddler4_官方…

✨概率论期末速成(三套卷)——试卷①✨

✨博主&#xff1a;命运之光 ✨专栏&#xff1a;概率论期末速成&#xff08;三套卷&#xff09; 目录 ✨一、填空题&#xff08;在下列各题填写正确答案&#xff0c;不填、填错&#xff0c;该题无分&#xff0c;每小题3分&#xff0c;共36分&#xff09;✨二、计算题(本大题6小…

《2023金融科技十大趋势报告》重磅发布:安全成为金融科技发展生命线

5月23日&#xff0c;由腾讯研究院、腾讯云、腾讯安全、微信支付、腾讯广告、腾讯优图实验室、招商银行、中信建投证券联合编制的《2023金融科技十大趋势报告》&#xff08;以下简称《报告》&#xff09;正式发布。《报告》从创新篇、智能篇、普惠篇、安全篇、融合篇五个方面总结…

虎牙直播在微服务改造的实践总结2

博主介绍&#xff1a;✌全网粉丝4W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战、定制、远程&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面…

常用的Jmeter参数化技巧总结,总有一个你不知道

说起接口测试&#xff0c;相信大家在工作中用的最多的还是Jmeter。 JMeter是一个100&#xff05;的纯Java桌面应用&#xff0c;由Apache组织的开放源代码项目&#xff0c;它是功能和性能测试的工具。具有高可扩展性、支持Web(HTTP/HTTPS)、SOAP、FTP、JAVA 等多种协议。 在做…

安全狗云原生安全能力亮相2023年智能汽车信息安全大会

5月19日&#xff0c;2023年智能汽车信息安全大会在上海顺利落幕。作为国内云原生安全领导厂商&#xff0c;安全狗受邀出席此次活动。 据悉&#xff0c;在领导致辞后&#xff0c;来自汽车行业以及网络安全行业的专家们就智能汽车涉及到的数据安全、安全合规、网络安全等话题展开…

Prompt Engineering | 迭代式优化和完善prompt

&#x1f604; 在尝试编写第一个 prompt时&#xff0c;满足上一博客说过的两个原则&#xff1a;清晰明确&#xff0c;并且给系统足够的时间思考。然后您可以运行它并查看结果。如果第一次效果不好&#xff0c;那么迭代的过程就是找出为什么指令不够清晰或为什么没有给算法足够的…

数据结构初阶——堆

目录 一&#xff0c;堆的概念 二&#xff0c;创建堆 2.1堆的结构 2.2堆的初始化 2.3堆的数据插入 2.4堆的数据的删除 注意点&#xff1a; 2.5 堆顶元素 2.6堆的长度 2.7堆的销毁 思维导图&#xff1a; 一&#xff0c;堆的概念 堆是什么&#xff1f;对于一个对于电脑储存结…

爆肝整理,接口测试到接口自动化测试小技巧,你的测试之路不再简单...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 Python自动化测试&…

Vue3 详细教程

文章目录 一、API 风格1.1 选项式 API1.2 组合式 API 二、Vue 指令2.1 {{}} 文本插值2.2 v-html 标签元素2.3 v-on 绑定事件2.4 v-show 隐藏元素2.5 v-if 消除元素2.6 v-bind 属性渲染2.7 v-for 列表渲染2.8 v-model 数据双向绑定 三、组件3.1 组件组合3.2 Props 组件交互3.3 自…

Linux:命令date、ntp查看和修改(校准)时间和地区。

Linux&#xff1a;命令date、ntp查看和修改&#xff08;校准&#xff09;时间和地区。 date -d 不仅可以1还可以加其他数字&#xff0c;表达后多久&#xff0c;-表达前多久&#xff1a; 备注&#xff1a;中国所在的时区是东八区 单独使用date时&#xff0c;会出现一串内容&…

Linux驱动入门——基础概念

文章目录 Linux内核简介Unix的历史Linux简介操作系统和内核简介单内核与微内核设计之比较小结 设备驱动简介驱动程序的角色划分内核设备和模块的分类安全问题版权条款 Linux驱动开发概述驱动程序概述设备驱动程序的作用设备驱动的分类Linux操作系统与驱动的关系Linux驱动开发编…