demo mvc 微信开发_java开发微信公众号调用微信扫一扫demo - CSDN
精华内容
参与话题
  • 2019 最新 .Net MVC微信授权登录及支付详解附源代码,包括微信授权登录操作步骤,微信支付操作步骤包括本人开放过程中才过的坑
  • MVC开发微信公众号

    热门讨论 2020-07-30 23:32:27
    MVC模式的微信公众平台接口开发DEMO,验证。
  • .NET MVC 微信扫码登录

    2020-07-30 23:30:14
    .NET MVC 微信扫码登录,网站微信扫码登录,获取iconurl,openid,unionid,token等基本信息获取
  • 最近开发任务遇到了一个要在手机浏览器里面调起微信和支付宝去支付的开发需求,以前都是做的扫码支付或者JSAPI都是在软件内部支付的,没遇到过在自己浏览器内唤醒微信或者支付宝的支付这种开发开发的过程中遇到了...

    微信和支付宝H5支付

    最近开发任务遇到了一个要在手机浏览器里面调起微信和支付宝去支付的开发需求,以前都是做的扫码支付或者JSAPI都是在软件内部支付的,没遇到过在自己浏览器内唤醒微信或者支付宝的支付这种开发在开发的过程中遇到了许多问题和坑点这里就一一写进文章里面了

    首先放上支付宝和微信支付的开发文档

    支付宝手机网页支付
    微信H5支付

    由于是教程贴我们从一个新建的MVC项目开始

    MVC

    首先编写一个H5支付的页面
    选择支付
    代码如下所示:

    
    @{
        ViewBag.Title = "H5支付页";
        Layout = null;
    }
    <body>
        <script src="~/Scripts/jquery-3.4.1.js"></script>
        <script src="~/Scripts/bootstrap.min.js"></script>
        <link href="~/Content/bootstrap.min.css" rel="stylesheet" />
        <script src="~/Content/layer/layer.js"></script>
        <link href="~/Content/layer/theme/default/layer.css" rel="stylesheet" />
        
        <style>
            ul li {
                list-style: none;
                font-size: 40px;
                margin-bottom: 20px;
            }
    
            input {
                height: 50px !important;
                width: 50px !important;
                margin-left: 5%;
            }
    
            .head {
                background-color: darkblue;
                height: 100px;
                font-size: 40px;
                color: white;
                text-align: center;
            }
    
            .pay {
                width: 50%;
                margin: 5% 25%;
                border: 3px dashed lightgray;
                border-radius: 15px;
            }
    
            .btncolor {
                border-radius: 25px;
                background-color: #1E90FF;
                color: white;
            }
        </style>
        <form id="alitopay" action="支付宝后台处理网址" onsubmit="return sure();" method="post">
    
            <div style="text-align:center;margin:50px 0 0 0;font-size:40px">请选择支付方式</div>
            <img src="~/Images/weixin.png" class="pay" value="1" />
    
            <img id="zhifubao" src="~/Images/zhifubao.png" class="pay" value="2" />
    
            <div style="position:fixed;bottom:15%;width:100%;">
                <button class="btncolor" style="height:130px;margin:250px 5% 5% 5%;font-size:40px;width:90%;">确认支付</button>
            </div>
    
        </form>
    </body>
    
    <script>
        var paytype = "";
        function bordernone() {
            $(".pay").css("border", " 3px dashed lightgray");
    
        }
        $(".pay").click(function () {
            bordernone();
            $(this).css("border", "5px solid #1E90FF");
            paytype = $(this).attr("value");
        });
        function sure() {
            var Guid = $("#Guid").val();
            //paytype = $('input:radio:checked').val();
            if (paytype === "" || paytype === undefined) {
                layer.msg('<div style="font-size: 40px;margin-top:20px;">' + '请选择支付方式' + '</div>',
                    {
                        area: ["400px", "100px"]
                    });
                return false;
            } else if (paytype === 2) {//支付宝
                $('#alitopay').submit();
                return true;
            } else if (paytype == 1) {//微信
                $.ajax({
                    type: 'Post',
                    url: '微信后台处理网址',
                    data: { Guid: Guid },
                    dataType: 'json',
                    success: function (result) {
                        if (result.id > 0) {
                            window.location.href = result.result;
                        }
                    }
                });
                return false;
            }
        }
        $(document).ready(function () {
            $('.pay').trigger("click");
        })
    </script>
    
    
    

    这里我们首先讲解微信支付
    微信支付为了简单快捷我们用了盛派的SDK引入步骤如下
    1.首先右键项目选择管理Nuget程序包
    在这里插入图片描述

    安装盛派的dll

    需要值得注意的是我们要安装2个dll一个Senparc.Weixin一个 Senparc.Weixin.TenPay
    Pay

    安装完成后我们在跟目录的web.config添加以下内容

     <!-- 微信支付V3 -->
        <add key="TenPayV3_MchId" value="你的微信商户ID" />
        <add key="TenPayV3_Key" value="你的微信商户密钥" />
        <add key="TenPayV3_AppId" value="你的微信平台APPID" />
        <add key="TenPayV3_AppSecret" value="你的微信平台AppSecret" />
        <add key="TenPayV3_TenpayNotify" value="支付完成后回调通知地址" />
    

    在这里插入图片描述

    配置web.config后我们还要修改Global.asax

                //设置全局Debug 状态
                var isGLobalDebug = true;
                //全局设置参数,将被储存到 Senparc.CO2NET.Config.SenparcSetting
                var senparcSetting = SenparcSetting.BuildFromWebConfig(isGLobalDebug);
                //也可以通过这种方法在程序任意位置设置全局 Debug 状态:
                //Senparc.CO2NET.Config.IsDebug = isGLobalDebug;
    
    
                //CO2NET 全局注册,必须!!
                IRegisterService register = RegisterService.Start(senparcSetting).UseSenparcGlobal();
    
                //设置微信 Debug 状态
                var isWeixinDebug = true;
                //全局设置参数,将被储存到 Senparc.Weixin.Config.SenparcWeixinSetting
                var senparcWeixinSetting = SenparcWeixinSetting.BuildFromWebConfig(isWeixinDebug);
                //也可以通过这种方法在程序任意位置设置微信的 Debug 状态:
                //Senparc.Weixin.Config.IsDebug = isWeixinDebug;
    
                //微信全局注册,必须!!
                register.UseSenparcWeixin(senparcWeixinSetting, senparcSetting)
                .RegisterTenpayV3(senparcWeixinSetting, "XXX公众号");
                //记录到同一个 SenparcWeixinSettingItem 对象中
    

    Global

    此处修改完成后我们就可以动手开始写controller了
    paycontroller

    支付代码如下:

    using Senparc.Weixin.Helpers;
    using Senparc.Weixin.TenPay;
    using Senparc.Weixin.TenPay.V3;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Web;
    using System.Web.Mvc;
    
    namespace TestPay.Controllers
    {
        public class WeiXinController : Controller
        {
            private static TenPayV3Info _tenPayV3Info;
            public static TenPayV3Info TenPayV3Info
            {
                get
                {
                    if (_tenPayV3Info == null)
                    {
    
                        var key = TenPayHelper.GetRegisterKey(Senparc.Weixin.Config.SenparcWeixinSetting);
                        _tenPayV3Info =
                            TenPayV3InfoCollection.Data[key];
                    }
                    return _tenPayV3Info;
                }
            }
    
            // GET: WeiXin
            public ActionResult H5Pay()
            {
    
                string total_amout = null;//支付价格
                string Guid = GetSerialNumber();//系统内订单号我这里是生成的时间+随机数字//注意不要超过32位否则微信会报错
    
                // 商品描述
                string body = "测试支付";
                string openId = "";
                var timeStamp = TenPayV3Util.GetTimestamp();//时间戳
                var nonceStr = TenPayV3Util.GetNoncestr();
    
                var price = total_amout == null ? 1 : int.Parse(total_amout) * 100;//注意微信支付单位为分所以要100  如果传1就是1分钱 传100就是1块钱
                //var ip = Request.Params["REMOTE_ADDR"];
                var xmlDataInfo = new TenPayV3UnifiedorderRequestData(TenPayV3Info.AppId, TenPayV3Info.MchId, body, Guid, price, Request.UserHostAddress, TenPayV3Info.TenPayV3Notify, TenPayV3Type.MWEB/*此处无论传什么,方法内部都会强制变为MWEB*/, openId, TenPayV3Info.Key, nonceStr);
    
                var result = TenPayV3.Html5Order(xmlDataInfo);//调用统一订单接口
                                                              //JsSdkUiPackage jsPackage = new JsSdkUiPackage(TenPayV3Info.AppId, timeStamp, nonceStr,);
                var package = string.Format("prepay_id={0}", result.prepay_id);//预支付订单id
    
                string paysign = TenPayV3.GetJsPaySign(TenPayV3Info.AppId, timeStamp, nonceStr, package, TenPayV3Info.Key);//签名sign
    
                //设置成功页面(也可以不设置,支付成功后默认返回来源地址)
                string returnUrl = "";
    
    
                string hosturl = Request.Url.Host;
    
                returnUrl =hosturl+ "/WeiXin/PayOK";//支付成功后跳转网址
    
    
    
                var mwebUrl = result.mweb_url;
                if (!string.IsNullOrEmpty(returnUrl))
                {
                    mwebUrl += string.Format("&redirect_url={0}", AsUrlData(returnUrl));
                }
                return Json(new { id = 1, result = mwebUrl });
            }
    
    
            #region  url处理
            public static string AsUrlData(string data)
            {
                if (data == null)
                {
                    return null;
                }
                return Uri.EscapeDataString(data);
            }
    
            #endregion
    
    
            #region  生成随机流水或
    
            private static long np1 = 0, np2 = 0, np3 = 1; //临时计算用。
            private static object orderFormNumberLock = new object();//线程并行锁,以保证同一时间点只有一个用户能够操作流水号。如果分多个流水号段,放多个锁,并行压力可以更好的解决,大家自己想法子扩充吧
            private string strOrderNumber = null;//订单号。
            /// <summary>
            /// 生成充值流水号格式:8位日期加8位顺序号,如2010030200000056。
            /// </summary>
            public string GetSerialNumber()
            {
          
                DateTime now = DateTime.Now;
                TimeSpan span = now - DateTime.MinValue;
                long tmpDays = span.Days;
                long seconds = span.Hours * 3600 + span.Seconds;
                StringBuilder sb = new StringBuilder();
                Monitor.Enter(orderFormNumberLock); //锁定资源
                if (tmpDays != np1)
                {
                    np1 = tmpDays;
                    np2 = 0;
                    np3 = 1;
                }
                if (np2 != seconds)
                {
                    np2 = seconds;
                    np3 = 1;
                }
                sb.Append(Convert.ToString(np1, 16).PadLeft(5, '0') + Convert.ToString(np2, 16).PadLeft(5, '0') + Convert.ToString(np3++, 16).PadLeft(6, '0'));
                Monitor.Exit(orderFormNumberLock); //释放资源
                strOrderNumber = sb.ToString();
                return strOrderNumber;
            }
            #endregion
        }
    
    }
    

    完成后我们选择微信支付如下图所示吊起微信
    微信支付

    完成微信支付后我们开始支付宝的开发

    同样支付宝支付我们需要一个AliPay.AopSDK的dll
    AliPay.AopSDK

    我们再次将配置需要的参数写入web.config中

        <!--应用ID,您的APPID-->
        <add key="app_id" value="xxxxxxxxx" />
        <add key="gatewayUrl" value="https://openapi.alipay.com/gateway.do" />
        <!--商户私钥,您的原始格式RSA私钥-->
        <add key="private_key" value="xxxxxxx" />
        <!--支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。-->
        <add key="alipay_public_key" value="xxxxxxx" />
        <add key="sign_type" value="RSA2" />
        <add key="charset" value="UTF-8" />
    
    

    controller 如下所示

    using Aop.Api;
    using Aop.Api.Domain;
    using Aop.Api.Request;
    using Aop.Api.Response;
    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    namespace TestPay.Controllers
    {
        public class AliPayController : Controller
        {
            // GET: AliPay
    
            [HttpPost]
            public void ALiPay()
            {
    
                string gatewayUrl = ConfigurationManager.AppSettings["gatewayUrl"].ToString();
                string app_id = ConfigurationManager.AppSettings["app_id"].ToString();
                string private_key = ConfigurationManager.AppSettings["private_key"].ToString();
                string sign_type = ConfigurationManager.AppSettings["sign_type"].ToString();
                string alipay_public_key = ConfigurationManager.AppSettings["alipay_public_key"].ToString();
                string charset = ConfigurationManager.AppSettings["charset"].ToString();
    
                DefaultAopClient client = new DefaultAopClient(gatewayUrl, app_id,private_key, "json", "1.0", sign_type, alipay_public_key, charset, false);
    
                string hosturl = Request.Url.Host;
    
    
                // 外部订单号,商户网站订单系统中唯一的订单号
                string out_trade_no = Helper.GetSerialNumber();//系统内订单号我这里是生成的时间+随机数字//注意不要超过64位否则微信会报错
    
                // 订单名称
                string subject = "测试支付";
    
    
                // 付款金额
                string total_amout = "0.01";
    
                //string total_amout = "0.01";
    
    
                // 商品描述
                string body = "测试支付";
                string quit_url = "";
    
    
                // 支付中途退出返回商户网站地址
                quit_url = hosturl + "H5pay/Index";
    
    
                // 组装业务参数model
                AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
                model.Body = body;
                model.Subject = subject;
                model.TotalAmount = total_amout;
                model.OutTradeNo = out_trade_no;
                model.ProductCode = "QUICK_WAP_WAY";
                model.QuitUrl = quit_url;
    
                AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
    
    
                // 设置支付完成同步回调地址
                request.SetReturnUrl(hosturl + "H5pay/PayOK");
                // 设置支付完成异步通知接收地址
                request.SetNotifyUrl(hosturl + "H5pay/Notify_url");
    
    
    
                // 将业务model载入到request
                request.SetBizModel(model);
    
                AlipayTradeWapPayResponse response = null;
                try
                {
                    response = client.pageExecute(request, null, "post");
                    Response.Write(response.Body);
    
                }
                catch (Exception exp)
                {
    
                    throw exp;
    
                }
            }
        }
    }
    
    

    完成后代码效果如下
    支付宝
    支付宝2

    写完支付后其实还有一步重要的步骤就是支付回调

    微信支付回调

    #region 微信回调方法
            [HttpPost]
            public ActionResult PayNotifyUrl()
            {
    
                try
                {
                    ResponseHandler resHandler = new ResponseHandler(null);
    
                    string return_code = resHandler.GetParameter("return_code");//支付结果
                    string return_msg = resHandler.GetParameter("return_msg");//支付消息
    
    
    
    
                    bool paySuccess = false;
    
                    resHandler.SetKey(TenPayV3Info.Key);
                    //验证请求是否从微信发过来(安全)
                    if (resHandler.IsTenpaySign() && return_code.ToUpper() == "SUCCESS")
                    {
                        paySuccess = true;//正确的订单处理
                        //直到这里,才能认为交易真正成功了,可以进行数据库操作,但是别忘了返回规定格式的消息!
                    }
                    else
                    {
                        paySuccess = false;//错误的订单处理
                    }
    
                    if (paySuccess)
                    {
                        /* 这里可以进行订单处理的逻辑 */
    
                        //发送支付成功的模板消息
                        try
                        {
                            string appId = Senparc.Weixin.Config.SenparcWeixinSetting.WeixinAppId;//与微信公众账号后台的AppId设置保持一致,区分大小写。
                            int total_fee = int.Parse(resHandler.GetParameter("total_fee"));//订单金额
                            string out_trade_no = resHandler.GetParameter("out_trade_no");//商户订单号
                            string transaction_id = resHandler.GetParameter("transaction_id");//商户订单号
    
    
                          
                            //在此处编写支付成功的逻辑
    
    
    
                        }
                        catch (Exception ex)
                        {
                           
                        }
    
                    }
    
                    string xml = string.Format(@"<xml>
    <return_code><![CDATA[{0}]]></return_code>
    <return_msg><![CDATA[{1}]]></return_msg>
    </xml>", return_code, return_msg);
                    return Content(xml, "text/xml");
                }
                catch (Exception ex)
                {
                  
                    throw;
                }
    
    
            }
    
            #endregion
    

    支付宝支付回调

      #region 支付宝回调方法
            [HttpPost]
            public ActionResult Notify_url()
            {
                /* 实际验证过程建议商户添加以下校验。
                        1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
                        2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
                        3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)
                        4、验证app_id是否为该商户本身。
                        */
                Dictionary<string, string> sArray = GetRequestPost();
                string gatewayUrl = ConfigurationManager.AppSettings["gatewayUrl"].ToString();
                string app_id = ConfigurationManager.AppSettings["app_id"].ToString();
                string private_key = ConfigurationManager.AppSettings["private_key"].ToString();
                string sign_type = ConfigurationManager.AppSettings["sign_type"].ToString();
                string alipay_public_key = ConfigurationManager.AppSettings["alipay_public_key"].ToString();
                string charset = ConfigurationManager.AppSettings["charset"].ToString();
    
                if (sArray.Count != 0)
                {
                    bool flag = AlipaySignature.RSACheckV1(sArray, alipay_public_key,charset, sign_type, false);
                    if (flag)
                    {
                        //交易状态
                        //判断该笔订单是否在商户网站中已经做过处理
                        //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
                        //请务必判断请求时的total_amount与通知时获取的total_fee为一致的
                        //如果有做过处理,不执行商户的业务程序
    
                        //注意:
                        //退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知
                        string trade_status = Request.Form["trade_status"];
    
                        //商户订单号
                        string out_trade_no = Request.Form["out_trade_no"];
    
    
                        //支付宝交易号
                        string trade_no = Request.Form["trade_no"];
    
    
    
                        string total_amount = Request.Form["total_amount"];
    
    
                        if (trade_status == "TRADE_FINISHED" || trade_status == "TRADE_SUCCESS")
                        {
    
                            
                            try
                            {
                               //在此处编写你的支付成功的逻辑
                               return Json("success");
                               
                            }
                            catch (Exception e)
                            {
                                return Json("fail");
                            }
    
                        }
                        else if (trade_status == "TRADE_CLOSED")
                        {
                            return Json("fail");
    
                        }
                        return Json("success");
                    }
                    else
                    {
    
                        return Json("fail");
    
                    }
                }
                return Json("fail");
            }
    
    
            public Dictionary<string, string> GetRequestPost()
            {
                int i = 0;
                Dictionary<string, string> sArray = new Dictionary<string, string>();
                NameValueCollection coll;
                //coll = Request.Form;
                coll = Request.Form;
                String[] requestItem = coll.AllKeys;
                for (i = 0; i < requestItem.Length; i++)
                {
                    sArray.Add(requestItem[i], Request.Form[requestItem[i]]);
                }
                return sArray;
    
            }
    
          #endregion
    
    
    

    因为很多人私信我弄不明白支付宝的参数肿么弄,我这里重新在最后讲下支付宝支付参数的设置

    1.下载支付宝密钥生成工具:下载地址
    在这里插入图片描述
    2.运行程序,按下图所示生成密钥
    在这里插入图片描述
    配置里面的私钥就是生成的私钥在这里插入图片描述
    而下面的支付宝公钥需要在支付宝后台
    在这里插入图片描述
    将你生成的应用公钥复制到对应的位置确认后网页会返回给你一个支付宝公钥这个支付宝公钥就是填入配置所需的参数

    在这里插入图片描述
    在这里插入图片描述
    最后需要源码都请扫码关注回复:H5源码
    获取下载地址
    在这里插入图片描述

    展开全文
  • 微信公众平台接入:其实很简单,把两个参数(地址和token)填入微信公众平台后台,暂时选择明文模式 ,其中token自己定义。微信服务器会根据后台填写的地址访问,并且带上对于的参数 如 url+&signature=0dab3e6f...

    微信公众平台接入:其实很简单,把两个参数(地址和token)填入微信公众平台后台,暂时选择明文模式 ,其中token自己定义。微信服务器会根据后台填写的地址访问,并且带上对于的参数 如 url+&signature=0dab3e6f983b6bdccfdbe3ceca01526f1522748a&timestamp=1436257899&nonce=1868246535&echostr=echostr 根据参数用微信文档中指定的方法加密检验是否来自微信然后返回随机数echostr(当然你可以直接返回随机数,好处是简单,但是这样非微信服务器也可以访问你的服务器

    此处的方法是:新建一个一般处理程序(通常的做法是有伪静态处理,不生成伪静态地址也可以)代码如下 token自定义,token类似密码,如果泄露和微信的密钥一样可以修改。因为接入非常简单这里就不多写,可以直接看代码。

    我写的demo测试地址为:http://wxdemo.sohovan.com/API.ashx  token:sohovan 下载源码的github地址:https://github.com/xiejun-net/weixin

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.SessionState;
    using System.Web.Security;
    
    namespace sohovan.com.wxdemo
    {
        /// <summary>
        /// API 的摘要说明
        /// </summary>
        public class API : IHttpHandler, IRequiresSessionState
        {
    
            public void ProcessRequest(HttpContext context)
            {
                context.Response.ContentType = "text/plain";
                if (context.Request.HttpMethod.ToLower() == "post")
                {
                    //回复消息的时候也需要验证消息,这个很多开发者没有注意这个,存在安全隐患  
                    //微信中 谁都可以获取信息 所以 关系不大 对于普通用户 但是对于某些涉及到验证信息的开发非常有必要
                    if (CheckSignature())
                    {
                        //接收消息
                    }
                    else
                    {
                        HttpContext.Current.Response.Write("消息并非来自微信");
                        HttpContext.Current.Response.End();
                    }
                }
                else
                {
                    CheckWechat();
                }
            }
    
            #region 验证微信签名
            /// <summary>
            /// 返回随机数表示验证成功
            /// </summary>
            private void CheckWechat()
            {
                if (string.IsNullOrEmpty(HttpContext.Current.Request.QueryString["echoStr"]))
                {
                    HttpContext.Current.Response.Write("消息并非来自微信");
                    HttpContext.Current.Response.End();
                }
                string echoStr = HttpContext.Current.Request.QueryString["echoStr"];
                if (CheckSignature())
                {
                    HttpContext.Current.Response.Write(echoStr);
                    HttpContext.Current.Response.End();
                }
            }
    
            /// <summary>
            /// 验证微信签名
            /// </summary>
            /// <returns></returns>
            /// * 将token、timestamp、nonce三个参数进行字典序排序
            /// * 将三个参数字符串拼接成一个字符串进行sha1加密
            /// * 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信。
            private bool CheckSignature()
            {
                string access_token = "sohovan";
    
                string signature = HttpContext.Current.Request.QueryString["signature"].ToString();
                string timestamp = HttpContext.Current.Request.QueryString["timestamp"].ToString();
                string nonce = HttpContext.Current.Request.QueryString["nonce"].ToString();
                string[] ArrTmp = { access_token, timestamp, nonce };
                Array.Sort(ArrTmp);     //字典排序
                string tmpStr = string.Join("", ArrTmp);
                tmpStr = FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA1");
    
                if (tmpStr.ToLower() == signature)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            #endregion
    
            public bool IsReusable
            {
                get
                {
                    return false;
                }
            }
        }
    }

    本文版权归作者(谢俊)和博客园所有,欢迎转载,转载请标明出处。

    原文地址:http://www.cnblogs.com/net-xiejun/

    微信开发群C#.NETWEB程序开发交流

    完整源码下载:https://github.com/xiejun-net/weixin

    个人公众账号:

    转载于:https://www.cnblogs.com/net-xiejun/p/4628489.html

    展开全文
  • 今天,我们接着讲微信支付的系列教程,前面,我们讲了这个微信红包和扫码支付。现在,我们讲讲这个公众号支付。公众号支付的应用环境常见的用户通过公众号,然后再通过公众号里面的菜单链接,进入公众号的商城,然后...

    今天,我们接着讲微信支付的系列教程,前面,我们讲了这个微信红包和扫码支付。现在,我们讲讲这个公众号支付。公众号支付的应用环境常见的用户通过公众号,然后再通过公众号里面的菜单链接,进入公众号的商城,然后在里面完成购买和支付功能,我们可以看看官方对这个公众号支付的场景的解释,链接:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1,通过这个官方的解释,那我们大概清楚这个公众号的用途了,下面,我就说说,做这个公众号支付的准备工作有哪些了。

     1、下载微信web开发者工具,工具的使用方式,也看链接,地址:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455784140&token=&lang=zh_CN

      2、配置“微信支付”环境,如下图:

    3、授权获取用户信息,如下图:

     下面开始,一步一步往下走。

     一、我们先开发程序,首先,新建一个MVC工程(asp.net的话,官方给的demo就是asp.net的,可以下载来参考:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1),名为:微信支付之公众号支付,如下图:

     

    然后右键项目,我们修改一下属性,如下图:

     

    然后我们再把程序自动生成的HomeController.cs和View里面的删掉,再新建一个HomeController.cs和添加View,代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
     
    namespace Web.Controllers
    {
     public class HomeController : Controller
     {
      // GET: Home
      public ActionResult Index()
      {
       return View();
      }
     }
    }

    View代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    @{
     Layout = null;
    }
     
    <!DOCTYPE html>
     
    <html>
    <head>
     <meta name="viewport" content="width=device-width" />
     <title>Index</title>
    </head>
    <body>
     <div>
     </div>
    </body>
    </html>

    嗯,没错,目前还是空的,现在我们开始写前台,代码如下(我先贴上代码,后续再解释为啥这么做,因为如果一步步的写下去,按照前面两个的篇幅来,我觉得都可以开课了,所以,我先上代码,然后再一步步解释。):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    @{
     Layout = null;
    }
     
    <!DOCTYPE html>
     
    <html>
    <head>
     <meta name="viewport" content="width=device-width" />
     <title>电表充值服务</title>
     <link href="~/Scripts/jquery-easyui-1.4.5/themes/bootstrap/easyui.css" rel="stylesheet" />
     <link href="~/Scripts/jquery-easyui-1.4.5/themes/mobile.css" rel="stylesheet" />
     <link href="~/Scripts/jquery-easyui-1.4.5/themes/icon.css" rel="stylesheet" />
     <style type="text/css">
      body{
       margin:0;
       padding:0;
      }
      .logo {
       width: 100%;
       height: 70px;
       background: url(/Images/EleLogo.png) 0 0 no-repeat;
       background-size: 100% 100%;
       padding: 0;
       margin: 0;
      }
     
      .line {
       width: 100%;
       float: left;
       height: auto;
       text-align: center;
       margin-top: 10px;
      }
     
      .lineText {
       width: 100%;
       float: left;
       height: auto;
       text-indent: 5%;
       text-align: left;
       font-size: x-large;
       margin: 0;
      }
     
      .function {
       height: 60pt;
       line-height: 60pt;
       width: 45%;
       float: left;
       border-radius: 10px;
       background-color: #990000;
       margin-left: 8pt;
      }
     
      .title {
       font-family: "微软雅黑";
       font-size: x-large;
       color: white;
      }
     
      a {
       text-decoration: none;
       color: white;
      }
     
      input {
       vertical-align: central;
      }
     
      label {
       vertical-align: central;
      }
     
      .lbBlock {
       border: 1px solid #808080;
       background-color: grey;
       width: 90%;
       margin-left: 5%;
       font-size: x-large;
       border-radius: 10px;
       text-align: left;
       text-indent: 10pt;
       height: 30pt;
       padding-top: 5pt;
      }
     
      .btn {
       width: 90%;
       height: 35pt;
       font-size: x-large;
       background-color: #990000;
       color: white;
       background: url(/Images/red.png) 0 0 repeat;
       border: none;
       border-radius: 10px;
       margin: 10px 0 0 0;
      }
     
      .input {
       height: 30pt;
       width: 90%;
       font-size: x-large;
       border-radius: 10px;
       margin: 0;
       padding: 0;
      }
     </style>
     
    </head>
    <body>
     <div class="logo">
     </div>
     <form id="ChargeForm"
      <div class="line">
       <div class="lineText">
        充值金额:
       </div>
      </div>
      <div class="line">
       <input type="number" id="ChargeVal" name="ChargeVal" class="input" placeholder="单位:元" />
      </div> 
     </form>
     <div class="line">
      <input type="button" class="btn" value="立即充值" onclick="fCharge()" style="margin-top: 20px;" />
     </div>
     <div class="line">
      <input type="button" id="btnHome" class="btn" value="返回主页" onclick="fBackHome()" />
     </div>
     <script src="~/Scripts/jquery-easyui-1.4.5/jquery.min.js"></script>
     <script src="~/Scripts/jquery-easyui-1.4.5/jquery.easyui.min.js"></script>
     <script src="~/Scripts/jquery-easyui-1.4.5/jquery.easyui.mobile.js"></script>
     <script src="~/Scripts/jquery-easyui-1.4.5/easyloader.js"></script>
     <script type="text/javascript">
      $(function () {
       var vCode = getQueryString("code");
       if (vCode != "" && vCode != null) {
        //alert(vCode);
        $.ajax({
         type: 'post',
         data: {
          code: vCode
         },
         url: '/Home/getWxInfo',
         success: function (sjson) {
          //alert(sjson);
          //var vData = JSON.stringify(sjson);
          //alert(vData);
          $.messager.show({
           title: '提示',
           msg: '欢迎您来到微信端充值中心。'
          });
         }
        })
       }
       else {
        $.ajax({
         type: 'post',
         url: '/Home/getCode',
         success: function (sjson) {
          //alert(sjson);
          location.href = sjson;
         }
        })
       }
      })
      //获取url的参数
      function getQueryString(name) {
       var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
       var r = window.location.search.substr(1).match(reg);
       if (r != null) return unescape(r[2]); return null;
      }
     
     
     
     
     
      //初始化微信支付环境
      function fCharge() {
       if (typeof WeixinJSBridge == "undefined") {
        if (document.addEventListener) {
         document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
        } else if (document.attachEvent) {
         document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
         document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
        }
       } else {
        fPostCharge();
       }
      }
      //提交充值数据
      function fPostCharge() {
       var vChargeVal = $("#ChargeVal").val();
       vChargeVal = parseFloat(vChargeVal);
       if (vChargeVal > 0) {
        $.messager.progress({
         title: "",
         msg: "正在调用微信支付接口,请稍后..."
        });
        $.ajax({
         type: "post",
         data: "totalfee=" + vChargeVal,
         url: "/Home/MeterRecharge",
         success: function (json) {
          $.messager.progress('close');//记得关闭
          //var json = eval("(" + msg + ")");//转换后的JSON对象
          onBridgeReady(json);
         },
         error: function () {
          $.messager.progress('close');//记得关闭
          $.messager.alert("提示", '调用微信支付模块失败,请稍后再试。', 'info')
         }
        })
       }
       else {
        alert("房间名或者充值金额不可以为空或者为负数,请确认后再试.")
       }
      }
      //调用微信支付模块
      function onBridgeReady(json) {
       WeixinJSBridge.invoke(
       'getBrandWCPayRequest', {
        "appId": json.appId,  //公众号名称,由商户传入
        "timeStamp": json.timeStamp,   //时间戳,自1970年以来的秒数
        "nonceStr": json.nonceStr, //随机串
        "package": json.packageValue,
        "signType": "MD5",   //微信签名方式:
        "paySign": json.paySign //微信签名
       },
       function (res) {
        if (res.err_msg == "get_brand_wcpay_request:ok") {
         //alert("支付成功,请稍后查询余额,如有疑问,请联系管理员.");
         fAlreadyPay();
        // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。
       }
       );
      }
      function fBackHome() {
       location.href = "/";
      }
     </script>
    </body>
    </html>

    后台代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using Web.Models;
    using WxPayAPI;
     
    namespace Web.Controllers
    {
     public class HomeController : Controller
     {
      JsApiPay jsApiPay = new JsApiPay();
      // GET: Home
      public ActionResult Index()
      {
       if (Session["openid"] == null)
       {
        try
        {
         //调用【网页授权获取用户信息】接口获取用户的openid和access_token
         GetOpenidAndAccessToken();
     
        }
        catch (Exception ex)
        {
         //Response.Write(ex.ToString());
         //throw;
        }
       }
       return View();
      }
     
     
      /**
      *
      * 网页授权获取用户基本信息的全部过程
      * 详情请参看网页授权获取用户基本信息:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
      * 第一步:利用url跳转获取code
      * 第二步:利用code去获取openid和access_token
      *
      */
      public void GetOpenidAndAccessToken()
      {
       if (Session["code"] != null)
       {
        //获取code码,以获取openid和access_token
        string code = Session["code"].ToString();
        Log.Debug(this.GetType().ToString(), "Get code : " + code);
        jsApiPay.GetOpenidAndAccessTokenFromCode(code);
       }
       else
       {
        //构造网页授权获取code的URL
        string host = Request.Url.Host;
        string path = Request.Path;
        string redirect_uri = HttpUtility.UrlEncode("http://" + host + path);
        //string redirect_uri = HttpUtility.UrlEncode("http://gzh.lmx.ren");
        WxPayData data = new WxPayData();
        data.SetValue("appid", WxPayConfig.APPID);
        data.SetValue("redirect_uri", redirect_uri);
        data.SetValue("response_type", "code");
        data.SetValue("scope", "snsapi_base");
        data.SetValue("state", "STATE" + "#wechat_redirect");
        string url = "https://open.weixin.qq.com/connect/oauth2/authorize?" + data.ToUrl();
        Log.Debug(this.GetType().ToString(), "Will Redirect to URL : " + url);
        Session["url"] = url;   
       }
      }
     
     
      /// <summary>
      /// 获取code
      /// </summary>
      /// <returns></returns>
      [HttpPost]
      public ActionResult getCode()
      {
       object objResult = "";
       if (Session["url"] != null)
       {
        objResult = Session["url"].ToString();
       }
       else
       {
        objResult = "url为空。";
       }
       return Json(objResult);
      }
     
      /// <summary>
      /// 通过code换取网页授权access_token和openid的返回数据
      /// </summary>
      /// <returns></returns>
      [HttpPost]
      public ActionResult getWxInfo()
      {
       object objResult = "";
       string strCode = Request.Form["code"];
       if (Session["access_token"] == null || Session["openid"] == null)
       {
        jsApiPay.GetOpenidAndAccessTokenFromCode(strCode);
       }
       string strAccess_Token = Session["access_token"].ToString();
       string strOpenid = Session["openid"].ToString();
       objResult = new { openid = strOpenid, access_token = strAccess_Token };
       return Json(objResult);
      }
     
     
     
     
      /// <summary>
      /// 充值
      /// </summary>
      /// <returns></returns>
      [HttpPost]
      public ActionResult MeterRecharge()
      {
       object objResult = "";
       string strTotal_fee = Request.Form["totalfee"];
       string strFee = (double.Parse(strTotal_fee) * 100).ToString();
     
       //若传递了相关参数,则调统一下单接口,获得后续相关接口的入口参数
       jsApiPay.openid = Session["openid"].ToString();
       jsApiPay.total_fee = int.Parse(strFee);
     
       //JSAPI支付预处理
       try
       {
        string strBody = "南宫萧尘微信支付";//商品描述
        WxPayData unifiedOrderResult = jsApiPay.GetUnifiedOrderResult(strBody);
        WxPayData wxJsApiParam = jsApiPay.GetJsApiParameters();//获取H5调起JS API参数,注意,这里引用了官方的demo的方法,由于原方法是返回string的,所以,要对原方法改为下面的代码,代码在下一段
     
        ModelForOrder aOrder = new ModelForOrder()
        {
         appId = wxJsApiParam.GetValue("appId").ToString(),
         nonceStr = wxJsApiParam.GetValue("nonceStr").ToString(),
         packageValue = wxJsApiParam.GetValue("package").ToString(),
         paySign = wxJsApiParam.GetValue("paySign").ToString(),
         timeStamp = wxJsApiParam.GetValue("timeStamp").ToString(),
         msg = "成功下单,正在接入微信支付."
        };
        objResult = aOrder;
       }
       catch (Exception ex)
       {
        ModelForOrder aOrder = new ModelForOrder()
        {
         appId = "",
         nonceStr = "",
         packageValue = "",
         paySign = "",
         timeStamp = "",
         msg = "下单失败,请重试,多次失败,请联系管理员."
        };
        objResult = aOrder;
       }
       return Json(objResult);
      }
     
     
     }
    }

    这里就是上面修改了的代码,童鞋们请注意

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    /**
    *
    * 从统一下单成功返回的数据中获取微信浏览器调起jsapi支付所需的参数,
    * 微信浏览器调起JSAPI时的输入参数格式如下:
    * {
    * "appId" : "wx2421b1c4370ec43b",  //公众号名称,由商户传入 
    * "timeStamp":" 1395712654",   //时间戳,自1970年以来的秒数 
    * "nonceStr" : "e61463f8efa94090b1f366cccfbbb444", //随机串 
    * "package" : "prepay_id=u802345jgfjsdfgsdg888", 
    * "signType" : "MD5",   //微信签名方式:
    * "paySign" : "70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名
    * }
    * @return string 微信浏览器调起JSAPI时的输入参数,json格式可以直接做参数用
    * 更详细的说明请参考网页端调起支付API:http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7
    *
    */
    public WxPayData GetJsApiParameters()
    {
     Log.Debug(this.GetType().ToString(), "JsApiPay::GetJsApiParam is processing...");
     
     WxPayData jsApiParam = new WxPayData();
     jsApiParam.SetValue("appId", unifiedOrderResult.GetValue("appid"));
     jsApiParam.SetValue("timeStamp", WxPayApi.GenerateTimeStamp());
     jsApiParam.SetValue("nonceStr", WxPayApi.GenerateNonceStr());
     jsApiParam.SetValue("package", "prepay_id=" + unifiedOrderResult.GetValue("prepay_id"));
     jsApiParam.SetValue("signType", "MD5");
     jsApiParam.SetValue("paySign", jsApiParam.MakeSign());
     
     string parameters = jsApiParam.ToJson();
     Log.Debug(this.GetType().ToString(), "Get jsApiParam : " + parameters);
     return jsApiParam;
    }

    ModelForOrder类的代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
     
    namespace Web.Models
    {
     public class ModelForOrder
     {
      public string appId { get; set; }
      public string timeStamp { get; set; }
      public string nonceStr { get; set; }
      public string packageValue { get; set; }
      public string paySign { get; set; }
     
      public string msg { get; set; }
     }
    }

    还有一个地方需要注意,修改一下的就是这里WxLib/business/JsApiPay.cs,如下图:

    最后,把程序发布出来,这次咱们把Web发布在http://gzh.lmx.ren上 ,然后再把接口权限,改为这样的,如下图:

     

    注意,这里面的域名和上面我们发布的域名要一致。 

    除此以外,我们还需要改这里:

    就是一定要授权这里,否则,支付的时候,会提示其他错误,具体,我就不测试了。

    另外,这里其实已经完成了这个公众号的支付的流程了,但是,我们页面上,会友善的提醒(其实不友善,提示是红色的,在头部,提示别输入密码什么),这是因为,我们还没把咱们这个http://gzh.lmx.ren域名设置为安全域名,设置之后,就不会在提示了。设置方法如下图:

    在这里面加入咱们的域名,就完美了。。。

     我的代码都尽量精简,多余的,我都会丢掉,就是为了避免混淆视听。如果代码里面,有写的不清楚的,可以私信问我,或群里来问我,群号在文章末端。

     现在,我开始一一解释我上面的做法。

    首先,在后端,页面加载的时候,他会先执行

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public ActionResult Index()
      {
       if (Session["openid"] == null)
       {
        try
        {
         //调用【网页授权获取用户信息】接口获取用户的openid和access_token
         GetOpenidAndAccessToken();
     
        }
        catch (Exception ex)
        {
         //Response.Write(ex.ToString());
         //throw;
        }
       }
       return View();
      }

     这里面就是为了获取用户的Openid和Access_token,这个用途很大,还有就是,我们通过代码可以知道,我们通过这个方法,可以获取到微信的一些相关信息,获取完了之后,他会返回到我们的页面上来,url就存在一个session里面,如下:

     Session["url"] = url;       

    接着,在前端:

    当页面加载完毕之后,会执行以下JS方法,如下:

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    $(function () {
      var vCode = getQueryString("code");
      if (vCode != "" && vCode != null) {
       //alert(vCode);
       $.ajax({
        type: 'post',
        data: {
         code: vCode
        },
        url: '/Home/getWxInfo',
        success: function (sjson) {
         //alert(sjson);
         //var vData = JSON.stringify(sjson);
         //alert(vData);
         $.messager.show({
          title: '提示',
          msg: '欢迎您来到微信端充值中心。'
         });
        }
       })
      }
      else {
       $.ajax({
        type: 'post',
        url: '/Home/getCode',
        success: function (sjson) {
         //alert(sjson);
         location.href = sjson;
        }
       })
      }
     })

    他会先获取浏览器的url,然后获取code,就是一般url后面的xxx.com?code=xxx,这里面就是首先判断有无code,如果没有code,则,我们去后台请求这个code。为什么请求这个code呢?我们来看这个方法: getWxInfo,如下图:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    /// <summary>
      /// 获取code
      /// </summary>
      /// <returns></returns>
      [HttpPost]
      public ActionResult getCode()
      {
       object objResult = "";
       if (Session["url"] != null)
       {
        objResult = Session["url"].ToString();
       }
       else
       {
        objResult = "url为空。";
       }
       return Json(objResult);
      }

    他就会返回url到前端,前端通过js去访问那个网址,那个网址就是微信端获取到我们的信息之后,给我们按照规则再返回一个url,这rul就是我们后面需要后去的code的url。这个code对我们至关重要,因为后面我们要做跟支付有关的工作,都用到的。有了code,我们才能拿到openid和access_token。具体看代码逻辑也可以明了。

    好,走到这一步,我们已经知道openid和access_token了,这个时候,我们就负责处理前端的东西。

    前端,我就一个金额输入框,然后一个提交,实际应用中,我们肯定还需要传入商品的参数,我这里面就不写那些多余的了,后续你们自己加进去就可以了。这里面在点击提交的时候,会调用微信的环境,看下面的代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    //初始化微信支付环境
     function fCharge() {
      if (typeof WeixinJSBridge == "undefined") {
       if (document.addEventListener) {
        document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
       } else if (document.attachEvent) {
        document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
        document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
       }
      } else {
       fPostCharge();
      }
     }

    他会初始化一下环境,如果初始化成功,代表,这个页面是在微信客户端里面运行的,那么我们就给他运行我们真正的充值代码提交,所以,就会执行:fPostCharge();

    提交之后,就会进入后台,后台需要组织我们前台需要用到的参数,其中包括如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    /// <summary>
      /// 充值
      /// </summary>
      /// <returns></returns>
      [HttpPost]
      public ActionResult MeterRecharge()
      {
       object objResult = "";
       string strTotal_fee = Request.Form["totalfee"];
       string strFee = (double.Parse(strTotal_fee) * 100).ToString();
     
       //若传递了相关参数,则调统一下单接口,获得后续相关接口的入口参数
       jsApiPay.openid = Session["openid"].ToString();
       jsApiPay.total_fee = int.Parse(strFee);
     
       //JSAPI支付预处理
       try
       {
        string strBody = "南宫萧尘微信支付";//商品描述
        WxPayData unifiedOrderResult = jsApiPay.GetUnifiedOrderResult(strBody);
        WxPayData wxJsApiParam = jsApiPay.GetJsApiParameters();//获取H5调起JS API参数
     
        ModelForOrder aOrder = new ModelForOrder()
        {
         appId = wxJsApiParam.GetValue("appId").ToString(),
         nonceStr = wxJsApiParam.GetValue("nonceStr").ToString(),
         packageValue = wxJsApiParam.GetValue("package").ToString(),
         paySign = wxJsApiParam.GetValue("paySign").ToString(),
         timeStamp = wxJsApiParam.GetValue("timeStamp").ToString(),
         msg = "成功下单,正在接入微信支付."
        };
        objResult = aOrder;
       }
       catch (Exception ex)
       {
        ModelForOrder aOrder = new ModelForOrder()
        {
         appId = "",
         nonceStr = "",
         packageValue = "",
         paySign = "",
         timeStamp = "",
         msg = "下单失败,请重试,多次失败,请联系管理员."
        };
        objResult = aOrder;
       }
       return Json(objResult);
      }

    我们主要需要提供的就是这个类ModelForOrder 里面的参数,然后再把这些参数返回给前台调用,如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    //调用微信支付模块
     function onBridgeReady(json) {
      WeixinJSBridge.invoke(
      'getBrandWCPayRequest', {
       "appId": json.appId,  //公众号名称,由商户传入
       "timeStamp": json.timeStamp,   //时间戳,自1970年以来的秒数
       "nonceStr": json.nonceStr, //随机串
       "package": json.packageValue,
       "signType": "MD5",   //微信签名方式:
       "paySign": json.paySign //微信签名
      },
      function (res) {
       if (res.err_msg == "get_brand_wcpay_request:ok") {
        //alert("支付成功,请稍后查询余额,如有疑问,请联系管理员.");
        fAlreadyPay();
       // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。
      }
      );
     }

    这样,他就会弹出一个微信支付的窗口,如下:

     

    然后我们确认付款之后,是否付款成功,如果付款成功,我们在执行: fAlreadyPay();

    这个方法已经被我删掉了,用途是用于,我们收到用户的款之后,我们需要同步一些数据到我们的数据库里面去,所以,该怎么操作,自己自行修改了。

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

    展开全文
  • C# MVC 微信支付教程系列之扫码支付

    千次阅读 2017-08-02 10:26:29
    微信官方的文档,这个扫码支付(NativePay)分为两种,一种是“生成扫描支付模式”,另外一种是“生成直接支付url,支付url有效期为2小时”,至于这里面,两种扫码模式,怎么灵活利用呢,官方也没有一个明确的说明。...
    微信官方的文档,这个扫码支付(NativePay)分为两种,一种是“生成扫描支付模式”,另外一种是“生成直接支付url,支付url有效期为2小时”,至于这里面,两种扫码模式,怎么灵活利用呢,官方也没有一个明确的说明。个人理解为,第一种(生成扫描支付模式),适用于固定二维码的,就是永久使用的那种,例如一些商家的公众号的二维码,是永久的,什么时候扫,都是关注这个公众号的,但是,这种的话,我记得微信是有限量的,貌似是一个公众号,限量10w,个人观点,觉得这个限量,是足够我们使用的。第二种(生成直接支付url,支付url有效期为2小时),这种的话,因为有有效期这种时间限制,超过了2个小时,该二维码就失效,但是对生成的二维码数量没有限制,所以,这种个人观点觉得适用于那种临时根据实际情况生成的二维码,例如:公众平台登陆的时候二次验证的二维码,自定义生成,仅为一次性缴费使用的二维码,等等)。接下来,我们就开始讲讲实际例子,首先将的就是第一种模式。
     
     
            扫码支付之模式一生成扫描支付模式
     
            首先,我们新建一个“MVC”的项目(asp.net的官方的demo就是了,要asp.net的自己看demo吧,demo地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1),然后把系统自动生成的HomeControler和View中的Home都删了。
     
            然后自己新建一个HomeControler,代码如下:
          // GET: Home
            public ActionResult Index()
            {
                return View();
            } 

     

     
                再添加一个View,代码如下:
    复制代码
    @{
        Layout = null;
    }
    <!DOCTYPE html>
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>首页</title>
    </head>
    <body>
        <div> 
        </div>
    </body>
    </html> 
    复制代码

     

     
    接下来,我们先把官方的demo的一些我们会用到的东西拷贝过来,其中包括以下几个文件夹,如下图:
     
     
    就这个lib和business两个,把这两个文件夹,支付复制到咱们的新项目中,并且包含在项目中,如下:
     
     
    然后我们再“重新生成”以下项目,或者快捷键:ctrl+shift+b,这时候,会提下如下错误:
     
     
    这时候,我们去添加引用,把lib文件夹中的LitJson.dll 添加上即可,如下图:
     
     
    到这里,我们就基本把官方的demo的环境给搭建好了,接下来,我们就要开始编写代码了。
     
            首先,我的逻辑是,从前到后,就是从前端到后端。前端是显示二维码的地方,那么我们就先给他一个div(本文使用到的是jquery的二维码生成插件,全名叫:jquery.qrcode.min.js,我会传到附件上),然后在页面加载完毕的时候,会请求后台,让他返回二维码字符串,然后再通过jquery的二维码生成插件,让他生成二维码并显示在前台,代码如下:
     
    前端:
    复制代码
    @{
        Layout = null;
    }
    <!DOCTYPE html>
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>首页</title>
        <link href="~/Scripts/jquery-easyui-1.4.5/themes/bootstrap/easyui.css" rel="stylesheet" />
        <link href="~/Scripts/jquery-easyui-1.4.5/themes/mobile.css" rel="stylesheet" />
        <link href="~/Scripts/jquery-easyui-1.4.5/themes/icon.css" rel="stylesheet" />
    </head>
    <body>
        <p>
            模式一:生成扫描支付模式
            <br />
            <div id="QRCode1">
            </div>
        </p>
        <p>
            模式二:生成直接支付url,支付url有效期为2小时
            <br />
            <div id="QRCode2">
            </div>
        </p>
        <script src="~/Scripts/jquery-1.10.2.js"></script>
        <script src="~/Scripts/jquery-easyui-1.4.5/jquery.easyui.min.js"></script>
        <script src="~/Scripts/jquery-easyui-1.4.5/jquery.easyui.mobile.js"></script>
        <script src="~/Scripts/jquery-easyui-1.4.5/easyloader.js"></script>
        <script src="~/Scripts/jquery.qrcode.min.js"></script>
        <script type="text/javascript">
            $(function () {
                fGetQRCode1();
            })
            function fGetQRCode1() {
                $.messager.progress({
                    title: "",
                    msg: "正在生成二维码:模式一,请稍后..."
                });
                $.ajax({
                    type: "post",
                    url: "/Home/GetQRCode1",
                    data: {
                        time: new Date(),
                        productId:7788
                    },
                    success: function (json) {
                        $.messager.progress('close');//记得关闭
                        if (json.result) {
                            $('#QRCode1').qrcode(json.str); //生成二维码
                        }
                        else {
                            $('#QRCode1').html("二维码生成失败");
                        }
                    }
                })
            }
        </script>
    </body>
    </html>
    复制代码

     

    后端:
    复制代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using WxPayAPI;
    namespace WxPay.Controllers
    {
        public class HomeController : Controller
        {
            // GET: Home
            public ActionResult Index()
            {
                return View();
            }
            /// <summary>
            /// 模式一
            /// </summary>
            /// <returns></returns>
            [HttpPost]
            public ActionResult GetQRCode1()
            {
                object objResult = "";
                string strProductID = Request.Form["productId"];
                string strQRCodeStr = GetPrePayUrl(strProductID);
                if (!string.IsNullOrWhiteSpace(strProductID))
                {
                    objResult = new { result = true, str = strQRCodeStr };
                }
                else
                {
                    objResult = new { result = false };
                }
                return Json(objResult);
            }
            /**
            * 生成扫描支付模式一URL
            * @param productId 商品ID
            * @return 模式一URL
            */
            public string GetPrePayUrl(string productId)
            {
                WxPayData data = new WxPayData();
                data.SetValue("appid", WxPayConfig.APPID);//公众帐号id
                data.SetValue("mch_id", WxPayConfig.MCHID);//商户号
                data.SetValue("time_stamp", WxPayApi.GenerateTimeStamp());//时间戳
                data.SetValue("nonce_str", WxPayApi.GenerateNonceStr());//随机字符串
                data.SetValue("product_id", productId);//商品ID
                data.SetValue("sign", data.MakeSign());//签名
                string str = ToUrlParams(data.GetValues());//转换为URL串
                string url = "weixin://wxpay/bizpayurl?" + str;
                return url;
            }
            /**
           * 参数数组转换为url格式
           * @param map 参数名与参数值的映射表
           * @return URL字符串
           */
            private string ToUrlParams(SortedDictionary<string, object> map)
            {
                string buff = "";
                foreach (KeyValuePair<string, object> pair in map)
                {
                    buff += pair.Key + "=" + pair.Value + "&";
                }
                buff = buff.Trim('&');
                return buff;
            }
        }
    }
    复制代码

     

    这时候,模式一是不是感觉就完成了?那么我们现在试试,我们浏览该页面,如下:
     
     
    然后用微信扫一扫功能扫一下,发现提示如下:
     
     
    这是什么鬼,是不是,你心里面是不是想知道为啥,那我来告诉你,这是为啥,这是因为,你还没有设置回调页面或者回调页面有问题,这个时候,我们再新建一个Control,命名为:NativeNotifyController.cs,代码如下:
    复制代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Web;
    using System.Web.Mvc;
    using WxPayAPI;
    namespace WxPay.Controllers
    {
        public class NativeNotifyController : Controller
        {
            // GET: NativeNotify
            public ActionResult Index()
            {
                string strData = ProcessNotify();
                Response.Write(strData);
                return View();
            }
            public string ProcessNotify()
            {
                WxPayData notifyData = GetNotifyData();
                //检查openid和product_id是否返回
                if (!notifyData.IsSet("openid") || !notifyData.IsSet("product_id"))
                {
                    WxPayData res = new WxPayData();
                    res.SetValue("return_code", "FAIL");
                    res.SetValue("return_msg", "回调数据异常");
                    return res.ToXml();
                }
                //调统一下单接口,获得下单结果
                string openid = notifyData.GetValue("openid").ToString();
                string product_id = notifyData.GetValue("product_id").ToString();
                WxPayData unifiedOrderResult = new WxPayData();
                try
                {
                    unifiedOrderResult = UnifiedOrder(openid, product_id);
                }
                catch (Exception ex)//若在调统一下单接口时抛异常,立即返回结果给微信支付后台
                {
                    WxPayData res = new WxPayData();
                    res.SetValue("return_code", "FAIL");
                    res.SetValue("return_msg", "统一下单失败");
                    return res.ToXml();
                }
                //若下单失败,则立即返回结果给微信支付后台
                if (!unifiedOrderResult.IsSet("appid") || !unifiedOrderResult.IsSet("mch_id") || !unifiedOrderResult.IsSet("prepay_id"))
                {
                    WxPayData res = new WxPayData();
                    res.SetValue("return_code", "FAIL");
                    res.SetValue("return_msg", "统一下单失败");
                    return res.ToXml();
                }
                //统一下单成功,则返回成功结果给微信支付后台
                WxPayData data = new WxPayData();
                data.SetValue("return_code", "SUCCESS");
                data.SetValue("return_msg", "OK");
                data.SetValue("appid", WxPayConfig.APPID);
                data.SetValue("mch_id", WxPayConfig.MCHID);
                data.SetValue("nonce_str", WxPayApi.GenerateNonceStr());
                data.SetValue("prepay_id", unifiedOrderResult.GetValue("prepay_id"));
                data.SetValue("result_code", "SUCCESS");
                data.SetValue("err_code_des", "OK");
                data.SetValue("sign", data.MakeSign());
                return data.ToXml();
            }
            /// <summary>
            /// 接收从微信支付后台发送过来的数据并验证签名
            /// </summary>
            /// <returns>微信支付后台返回的数据</returns>
            public WxPayData GetNotifyData()
            {
                //接收从微信后台POST过来的数据
                System.IO.Stream s = Request.InputStream;
                int count = 0;
                byte[] buffer = new byte[1024];
                StringBuilder builder = new StringBuilder();
                while ((count = s.Read(buffer, 0, 1024)) > 0)
                {
                    builder.Append(Encoding.UTF8.GetString(buffer, 0, count));
                }
                s.Flush();
                s.Close();
                s.Dispose();
                //转换数据格式并验证签名
                WxPayData data = new WxPayData();
                try
                {
                    data.FromXml(builder.ToString());
                }
                catch (WxPayException ex)
                {
                    //若签名错误,则立即返回结果给微信支付后台
                    WxPayData res = new WxPayData();
                    res.SetValue("return_code", "FAIL");
                    res.SetValue("return_msg", ex.Message);
                }
                return data;
            }
            private WxPayData UnifiedOrder(string openId, string productId)
            {
                //统一下单
                WxPayData req = new WxPayData();
                req.SetValue("body", "广东XXXX股份有限公司");
                req.SetValue("attach", "附加信息,用于后台或者存入数据库,做自己的判断");
                req.SetValue("out_trade_no", WxPayApi.GenerateOutTradeNo());
                req.SetValue("total_fee", 1);
                req.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss"));
                req.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss"));
                req.SetValue("goods_tag", "商品的备忘,可以自定义");
                req.SetValue("trade_type", "NATIVE");
                req.SetValue("openid", openId);
                req.SetValue("product_id", productId);
                WxPayData result = WxPayApi.UnifiedOrder(req);
                return result;
            }
        }
    }
    复制代码

     

     
     
    记得,也要新建一个View,就是在Index那里,右键添加一个View,View的代码如下(你没眼花,就是空的,不管他):
    复制代码
    @{
        Layout = null;
    }
    <!DOCTYPE html>
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Index</title>
    </head>
    <body>
        <div> 
        </div>
    </body>
    </html>
    复制代码

     

     
    接着,把这个项目,发布出来,放到服务器的iis上,这里面,我把他发布在http://sm.lmx.ren/上面(必须要发布到网上哈,如果不懂发布的,你可以自己去学习基础知识先了),这还没完,还需要把到公众平台上,设置回调页面,操作如下:
     
     
    这样,就大功告成了。这时候,我们再试试扫码,发现已经得到以下提示了,这样子,就代表,我们的模式一,已经成功完成了。如下图:
     
     
            这时候,细心的朋友就会提问了,我这都支付成功了,怎么页面没啥提示呀,这页面不交互很不友好啊。嗯,没错,童鞋,你有前途,现在我就告诉你,怎么做交互,但是,为了你日后更加有前途,我只告诉你逻辑,具体怎么实现,自己来想,多动脑。
     
           那么逻辑是怎么的呢?常规逻辑下,我们微信扫页面上的这个二维码的时候,这个时候,他已经把我们二维码里面的参数,传到微信服务器,然后有他们开始统一下单(如果对逻辑不清晰,可以看看官方的文档:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_3):他们在统一下单的时候,就会生成一个product_id,这个家伙的作用呢 ,就是告诉你现在微信服务器,已经生成了一个单号,劳资已经收到你的支付请求了,赶紧给老子付款,O(∩_∩)O哈哈~。。。停,停,停。这时候,思路不能继续往下走了。记得,前面有个叫做“统一下单“,那既然有这个步骤,那我们可以利用一下,就是当他统一下单成功的时候,我们可以在页面更新一下状态,告诉客户:您已成功扫描,并下单成功,请支付。是不是,我们可以提示他们这个。然后等用户在手机上,支付成功的时候,这个时候,页面是不是也要反馈给用户,告诉他,小子,你的钱已经到我的口袋了,你可以走了(你走,我没有你这样的宝宝)。O(∩_∩)O哈哈~,但是,你还要停,停住,停下来。我们服务公司怎么知道这个微信用户已经付款成功了呢?来,我们把视线回到代码上,找到lib/Config.cs,如下图:
     
    然后打开config.cs,找到以下代码:
     
     
    对了,你很聪明。微信的处理逻辑就是,等用户支付成功之后,他会给这个链接发送支付结果,默认是以前那个aspx的页面,现在我换成mvc,所以,我们得手动新建一个control了,命名为:ResultNotifyController然后代码如下:
    复制代码
    using LmxPublic.Log;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Web;
    using System.Web.Mvc;
    using WxPayAPI;
    namespace WxPay.Controllers
    {
        public class ResultNotifyController : Controller
        {
            // GET: ResultNotify
            public ActionResult Index()
            {
                string strData = ProcessNotify();
                Response.Write(strData);
                return View();
            }
            public string ProcessNotify()
            {
                WxPayData notifyData = GetNotifyData();
                //检查支付结果中transaction_id是否存在
                if (!notifyData.IsSet("transaction_id"))
                {
                    //若transaction_id不存在,则立即返回结果给微信支付后台
                    WxPayData res = new WxPayData();
                    res.SetValue("return_code", "FAIL");
                    res.SetValue("return_msg", "支付结果中微信订单号不存在");
                    return res.ToXml();
                }
                string transaction_id = notifyData.GetValue("transaction_id").ToString();
                //查询订单,判断订单真实性
                if (!QueryOrder(transaction_id))
                {
                    //若订单查询失败,则立即返回结果给微信支付后台
                    WxPayData res = new WxPayData();
                    res.SetValue("return_code", "FAIL");
                    res.SetValue("return_msg", "订单查询失败");
                    return res.ToXml();
                }
                //查询订单成功
                else
                {
                    WxPayData res = new WxPayData();
                    res.SetValue("return_code", "SUCCESS");
                    res.SetValue("return_msg", "OK");
                    Log.Info(this.GetType().ToString(), "order query success : " + res.ToXml());
                    string strXml = res.ToXml();
                    FileLog.WriteLog(strXml);
                    return res.ToXml();//如果我们走到这一步了,那就代表,用户已经支付成功了,所以,该干嘛干嘛了。
                }
            }
            /// <summary>
            /// 接收从微信支付后台发送过来的数据并验证签名
            /// </summary>
            /// <returns>微信支付后台返回的数据</returns>
            public WxPayData GetNotifyData()
            {
                //接收从微信后台POST过来的数据
                System.IO.Stream s = Request.InputStream;
                int count = 0;
                byte[] buffer = new byte[1024];
                StringBuilder builder = new StringBuilder();
                while ((count = s.Read(buffer, 0, 1024)) > 0)
                {
                    builder.Append(Encoding.UTF8.GetString(buffer, 0, count));
                }
                s.Flush();
                s.Close();
                s.Dispose();
                Log.Info(this.GetType().ToString(), "Receive data from WeChat : " + builder.ToString());
                //转换数据格式并验证签名
                WxPayData data = new WxPayData();
                try
                {
                    data.FromXml(builder.ToString());
                }
                catch (WxPayException ex)
                {
                    //若签名错误,则立即返回结果给微信支付后台
                    WxPayData res = new WxPayData();
                    res.SetValue("return_code", "FAIL");
                    res.SetValue("return_msg", ex.Message);
                    Log.Error(this.GetType().ToString(), "Sign check error : " + res.ToXml());
                    return res;
                }
                
                return data;
            }
            //查询订单
            private bool QueryOrder(string transaction_id)
            {
                WxPayData req = new WxPayData();
                req.SetValue("transaction_id", transaction_id);
                WxPayData res = WxPayApi.OrderQuery(req);
                if (res.GetValue("return_code").ToString() == "SUCCESS" &&
                    res.GetValue("result_code").ToString() == "SUCCESS")
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
    }
    复制代码

     

    前台,对,也是要新建一个View,代码如下(没错,也是空的)
     
    复制代码
    @{
        Layout = null;
    }
    <!DOCTYPE html>
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Index</title>
    </head>
    <body>
        <div> 
        </div>
    </body>
    </html>
    复制代码

     

     
    好,模式一就到这里了,呼呼。。。没想到啊,一个模式一,让我从上午写到下午,真心累。。。还有一个模式二呢。。。喝口水先,咱,接着来。
     
     
    好,喝完水,接着干,下面是模式二:
     

    模式二生成直接支付url,支付url有效期为2小时

     
    由于有了上面模式一的详细说明,模式二,我就简单一点的来说了,如果又不懂的,到群里来问我吧。
     
    模式二,前端,增加一些代码,如下(完整的,包括模式一的代码了):
     
    复制代码
    @{
        Layout = null;
    }
    <!DOCTYPE html>
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>首页</title>
        <link href="~/Scripts/jquery-easyui-1.4.5/themes/bootstrap/easyui.css" rel="stylesheet" />
        <link href="~/Scripts/jquery-easyui-1.4.5/themes/mobile.css" rel="stylesheet" />
        <link href="~/Scripts/jquery-easyui-1.4.5/themes/icon.css" rel="stylesheet" />
    </head>
    <body>
        <p>
            模式一:生成扫描支付模式
            <br />
            <div id="QRCode1">
            </div>
        </p>
        <p>
            模式二:生成直接支付url,支付url有效期为2小时
            <br />
            <div id="QRCode2">
            </div>
        </p>
        <script src="~/Scripts/jquery-1.10.2.js"></script>
        <script src="~/Scripts/jquery-easyui-1.4.5/jquery.easyui.min.js"></script>
        <script src="~/Scripts/jquery-easyui-1.4.5/jquery.easyui.mobile.js"></script>
        <script src="~/Scripts/jquery-easyui-1.4.5/easyloader.js"></script>
        <script src="~/Scripts/jquery.qrcode.min.js"></script>
        <script type="text/javascript">
            $(function () {
                fGetQRCode1();
            })
            function fGetQRCode1() {
                $.messager.progress({
                    title: "",
                    msg: "正在生成二维码:模式一,请稍后..."
                });
                $.ajax({
                    type: "post",
                    url: "/Home/GetQRCode1",
                    data: {
                        time: new Date(),
                        productId:7788
                    },
                    success: function (json) {
                        $.messager.progress('close');//记得关闭
                        if (json.result) {
                            $('#QRCode1').qrcode(json.str); //生成二维码
                        }
                        else {
                            $('#QRCode1').html("二维码生成失败");
                        }
                        fGetQRCode2();
                    },
                    error: function (json) {
                        $('#QRCode1').html("二维码生成失败");
                        fGetQRCode2();
                    }
                })
            }
            function fGetQRCode2() {
                $.messager.progress({
                    title: "",
                    msg: "正在生成二维码:模式二,请稍后..."
                });
                $.ajax({
                    type: "post",
                    url: "/Home/GetQRCode2",
                    data: {
                        time: new Date(),
                        productId: 7788
                    },
                    success: function (json) {
                        $.messager.progress('close');//记得关闭
                        if (json.result) {
                            $('#QRCode2').qrcode(json.str); //生成二维码
                        }
                        else {
                            $('#QRCode2').html("二维码生成失败");
                        }
                    },
                    error: function (json) {
                        $('#QRCode2').html("二维码生成失败");
                    }
                })
            }
        </script>
    </body>
    </html>
    复制代码

     

     
    后端:
     
    复制代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using WxPayAPI;
    namespace WxPay.Controllers
    {
        public class HomeController : Controller
        {
            // GET: Home
            public ActionResult Index()
            {
                return View();
            }
            /// <summary>
            /// 模式一
            /// </summary>
            /// <returns></returns>
            [HttpPost]
            public ActionResult GetQRCode1()
            {
                object objResult = "";
                string strProductID = Request.Form["productId"];
                string strQRCodeStr = GetPrePayUrl(strProductID);
                if (!string.IsNullOrWhiteSpace(strProductID))
                {
                    objResult = new { result = true, str = strQRCodeStr };
                }
                else
                {
                    objResult = new { result = false };
                }
                return Json(objResult);
            }
            /// <summary>
            /// 模式二
            /// </summary>
            /// <returns></returns>
            [HttpPost]
            public ActionResult GetQRCode2()
            {
                object objResult = "";
                string strProductID = Request.Form["productId"];
                string strQRCodeStr = GetPayUrl(strProductID);
                if (!string.IsNullOrWhiteSpace(strProductID))
                {
                    objResult = new { result = true, str = strQRCodeStr };
                }
                else
                {
                    objResult = new { result = false };
                }
                return Json(objResult);
            }
            /**
            * 生成扫描支付模式一URL
            * @param productId 商品ID
            * @return 模式一URL
            */
            public string GetPrePayUrl(string productId)
            {
                WxPayData data = new WxPayData();
                data.SetValue("appid", WxPayConfig.APPID);//公众帐号id
                data.SetValue("mch_id", WxPayConfig.MCHID);//商户号
                data.SetValue("time_stamp", WxPayApi.GenerateTimeStamp());//时间戳
                data.SetValue("nonce_str", WxPayApi.GenerateNonceStr());//随机字符串
                data.SetValue("product_id", productId);//商品ID
                data.SetValue("sign", data.MakeSign());//签名
                string str = ToUrlParams(data.GetValues());//转换为URL串
                string url = "weixin://wxpay/bizpayurl?" + str;
                return url;
            }
            /**
           * 参数数组转换为url格式
           * @param map 参数名与参数值的映射表
           * @return URL字符串
           */
            private string ToUrlParams(SortedDictionary<string, object> map)
            {
                string buff = "";
                foreach (KeyValuePair<string, object> pair in map)
                {
                    buff += pair.Key + "=" + pair.Value + "&";
                }
                buff = buff.Trim('&');
                return buff;
            }
            /**
           * 生成直接支付url,支付url有效期为2小时,模式二
           * @param productId 商品ID
           * @return 模式二URL
           */
            public string GetPayUrl(string productId)
            {
                WxPayData data = new WxPayData();
                data.SetValue("body", "广东XXXX股份有限公司");//商品描述
                data.SetValue("attach", "附加信息,用于后台或者存入数据库,做自己的判断");//附加数据
                data.SetValue("out_trade_no", WxPayApi.GenerateOutTradeNo());//随机字符串
                data.SetValue("total_fee", 1);//总金额
                data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss"));//交易起始时间
                data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss"));//交易结束时间
                data.SetValue("goods_tag", "商品的备忘,可以自定义");//商品标记
                data.SetValue("trade_type", "NATIVE");//交易类型
                data.SetValue("product_id", productId);//商品ID
                WxPayData result = WxPayApi.UnifiedOrder(data);//调用统一下单接口
                string url = result.GetValue("code_url").ToString();//获得统一下单接口返回的二维码链接
                
                return url;
            }
        }
    }
    复制代码

     

     特此更正,感谢“ abc54288”的指出,模式二也是有回调的,回调的接口设置在Config.cs,中,如下图:
     

    原文链接:http://www.cnblogs.com/nangong/p/9fa625bfb92a986125f0ba72704c46ec.html
    作者:南宫萧尘  
    E-mail:314791147@qq.com
    QQ:314791147
    日期:2016-05-28

    支付宝接口开发:http://www.cnblogs.com/webapi/p/6020393.html

    展开全文
  • C# MVC微信扫码支付

    2019-08-14 11:11:16
    建议开发前下载官方demo熟悉及后续有用到里面代码:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1 1.微信公众平台→支付配置→支付授权目录(授权目录就是指你要进行支付的目...
  • .net微信支付宝接口MVCDEMO 、.net微信支付宝接口MVCDEMO 、.net微信支付宝接口MVCDEMO
  • 【说明】:访客用户和外来施工人员用微信服务号;职工人员(内部人员)用企业微信号(企业号) 1、微信公众平台——服务号: (1)、从服务号授权获取信息登录的入口有:访客入口端和外来施工人员入口端两个。...
  • 微信支付接口类库及ASP.NET MVC DEMO
  • 上一篇文章讲到如何配置微信开发,以及.NET平台使用MVC做一个小DEMO的流程,还有常见收不到消息的问题...上一篇文章链接:[C#开发微信.NET平台MVC微信开发 发送普通消息Demo以及收不到消息的问题] (如果你是通过搜...
  • springMVC中微信公众平台开发

    千次阅读 2015-07-27 13:11:16
    servicepackage cn.bluemobi.service;import java.util.Arrays;import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional;import ...
  • 不得不说现在微信非常火,微信开放平台可以自己写程序跟用户交互,节省了前台开发成本,免去用户装客户端的烦恼。于是今天兴致来潮,想做一个试试。 首先找到了开发者文档,看了看,蛮简单的。(公众号早已申请,有...
  • 本文主要讲解asp.net mvc框架下公众号支付如何实现,公众号支付主要包括三个核心代码,前台调起支付js代码、对应js调用参数参数生成代码、支付成功处理代码。 一、微信支付方式介绍 微信提供了各种支付方式,试...
  • Deepleo.Weixin.SDK是SDK源代码 Deepleo.Web是一个asp.net mvcdemo
  • 微信支付教程系列之公众号支付 今天,我们接着讲微信支付的系列教程,前面,我们讲了这个微信红包和扫码支付。现在,我们讲讲这个公众号支付。公众号支付的应用环境常见的用户通过公众号,然后再通过公众号里面...
  • 目录 Demo最终效果 开发工具: 开发步骤: 第一步:准备工作,用visual studio写后台...刚自己做了一个开发微信小程序的Demo,怕忘了,记录下来。希望以后会跳过那些大坑~~ Demo最终效果 开发工具: ...
  • C# .net MVC 微信红包(服务号发送红包)

    千次阅读 2018-12-19 17:17:32
    C# .net MVC 微信红包(服务号发送红包) 注:需要开通微信支付的服务号! //跳转微信登录页面 public ActionResult Index() { ViewBag.url = &amp;quot;...
  • asp.net mvc微信支付服务端 demo

    千次阅读 2017-03-23 14:43:47
    微信开发文档没有服务器端的demo,然后我就找了一些资料做了一下,没想到一次就成功了,记录一下。 第一步获取prepay_id UnifiedOrder uo = new UnifiedOrder(); uo.appid = appid; uo.mch_id = mch_id;
1 2 3 4 5 ... 20
收藏数 4,021
精华内容 1,608
关键字:

demo mvc 微信开发