c#版在pc端发起微信扫码支付

来源:互联网 发布:网络广播电台小川 编辑:程序博客网 时间:2024/03/29 04:24

等了好久,微信官方终于发布了.net的demo。

技术分享

技术分享

主要代码:

/**        * 生成直接支付url,支付url有效期为2小时,模式二        * @param productId 商品ID        * @return 模式二URL        */        public string GetPayUrl(string productId, string body, string attach, int total_fee, string goods_tag)        {            Log.Info(this.GetType().ToString(), "Native pay mode 2 url is producing...");            WxPayData data = new WxPayData();            data.SetValue("body", body);//商品描述            data.SetValue("attach", attach);//附加数据            data.SetValue("out_trade_no", productId);//随机字符串            data.SetValue("total_fee", total_fee);//总金额            data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss"));//交易起始时间            data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss"));//交易结束时间            data.SetValue("goods_tag", 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();//获得统一下单接口返回的二维码链接            Log.Info(this.GetType().ToString(), "Get native pay mode 2 url : " + url);            return url;        }

配置信息:

public class Config    {        //=======【基本信息设置】=====================================        /* 微信公众号信息配置        * APPID:绑定支付的APPID(必须配置)        * MCHID:商户号(必须配置)        * KEY:商户支付密钥,参考开户邮件设置(必须配置)        * APPSECRET:公众帐号secert(仅JSAPI支付的时候需要配置)        */        public const string APPID = "你的微信公众号APPID";        public const string MCHID = "你的微信公众号的商户号";        public const string KEY = "你的微信公众号的商户支付密钥";        public const string APPSECRET = "你的微信公众号的APPSECRET";        //=======【证书路径设置】=====================================         /* 证书路径,注意应该填写绝对路径(仅退款、撤销订单时需要)        */        public const string SSLCERT_PATH = "cert/apiclient_cert.p12";        public const string SSLCERT_PASSWORD = "1233410002";        //=======【支付结果通知url】=====================================         /* 支付结果通知回调url,用于商户接收支付结果        */        public const string NOTIFY_URL = "http://你的网站/Pay/ResultNotifyPage.aspx";        //=======【商户系统后台机器IP】=====================================         /* 此参数可手动配置也可在程序中自动获取        */        public const string IP = "你的服务器IP";        //=======【代理服务器设置】===================================        /* 默认IP和端口号分别为0.0.0.0和0,此时不开启代理(如有需要才设置)        */        public const string PROXY_URL = "";        //=======【上报信息配置】===================================        /* 测速上报等级,0.关闭上报; 1.仅错误时上报; 2.全量上报        */        public const int REPORT_LEVENL = 1;        //=======【日志级别】===================================        /* 日志等级,0.不输出日志;1.只输出错误信息; 2.输出错误和正常信息; 3.输出错误信息、正常信息和调试信息        */        public const int LOG_LEVENL = 0;    }

不使用代理要注释HttpService.cs里面post和get方法的下面代码:

//设置代理服务器                //WebProxy proxy = new WebProxy();                          //定义一个网关对象                //proxy.Address = new Uri(Config.PROXY_URL);              //网关服务器端口:端口                //request.Proxy = proxy;

统一下单:

/**        *         * 统一下单        * @param WxPaydata inputObj 提交给统一下单API的参数        * @param int timeOut 超时时间        * @throws WxPayException        * @return 成功时返回,其他抛异常        */        public static WxPayData UnifiedOrder(WxPayData inputObj, int timeOut = 6)        {            string url = "https://api.mch.weixin.qq.com/pay/unifiedorder";            //检测必填参数            if (!inputObj.IsSet("out_trade_no"))            {                throw new WxPayException("缺少统一支付接口必填参数out_trade_no!");            }            else if (!inputObj.IsSet("body"))            {                throw new WxPayException("缺少统一支付接口必填参数body!");            }            else if (!inputObj.IsSet("total_fee"))            {                throw new WxPayException("缺少统一支付接口必填参数total_fee!");            }            else if (!inputObj.IsSet("trade_type"))            {                throw new WxPayException("缺少统一支付接口必填参数trade_type!");            }            //关联参数            if (inputObj.GetValue("trade_type").ToString() == "JSAPI" && !inputObj.IsSet("openid"))            {                throw new WxPayException("统一支付接口中,缺少必填参数openid!trade_type为JSAPI时,openid为必填参数!");            }            if (inputObj.GetValue("trade_type").ToString() == "NATIVE" && !inputObj.IsSet("product_id"))            {                throw new WxPayException("统一支付接口中,缺少必填参数product_id!trade_type为JSAPI时,product_id为必填参数!");            }            //异步通知url未设置,则使用配置文件中的url            if (!inputObj.IsSet("notify_url"))            {                inputObj.SetValue("notify_url", Config.NOTIFY_URL);//异步通知url            }            inputObj.SetValue("appid", Config.APPID);//公众账号ID            inputObj.SetValue("mch_id", Config.MCHID);//商户号            inputObj.SetValue("spbill_create_ip", Config.IP);//终端ip                          inputObj.SetValue("nonce_str", GenerateNonceStr());//随机字符串            //签名            inputObj.SetValue("sign", inputObj.MakeSign());            string xml = inputObj.ToXml();            var start = DateTime.Now;            Log.Debug("WxPayApi", "UnfiedOrder request : " + xml);            string response = HttpService.Post(xml, url, false, timeOut);            Log.Debug("WxPayApi", "UnfiedOrder response : " + response);            var end = DateTime.Now;            int timeCost = (int)((end - start).TotalMilliseconds);            WxPayData result = new WxPayData();            result.FromXml(response);            ReportCostTime(url, timeCost, result);//测速上报            return result;        }

看我的调用例子:

技术分享

MakeQRCode.aspx页面照抄:

public partial class Pay_MakeQRCode : System.Web.UI.Page{    protected void Page_Load(object sender, EventArgs e)    {        if (!string.IsNullOrEmpty(base.Request.QueryString["data"]))        {            string str = base.Request.QueryString["data"];            Bitmap image = new QRCodeEncoder            {                QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE,                QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M,                QRCodeVersion = 0,                QRCodeScale = 4            }.Encode(str, Encoding.Default);            MemoryStream ms = new MemoryStream();            image.Save(ms, ImageFormat.Png);            base.Response.BinaryWrite(ms.GetBuffer());            base.Response.End();        }    }}

这个页面是用来生成二维码的,需要引入ThoughtWorks.QRCode.dll组件。

我使用模式二,回调页面是ResultNotifyPage.aspx,就是在配置信息那里填写的那个回调页面。

protected void Page_Load(object sender, EventArgs e)    {        ResultNotify resultNotify = new ResultNotify(this);        WxPayData res = resultNotify.ProcessNotify2();        if (res.GetValue("return_code") == "SUCCESS")        {            //查询微信订单信息            string paySignKey = ConfigurationManager.AppSettings["paySignKey"].ToString();            string mch_id = ConfigurationManager.AppSettings["mch_id"].ToString();            string appId = ConfigurationManager.AppSettings["AppId"].ToString();            QueryOrder queryorder = new QueryOrder();            queryorder.appid = appId;            queryorder.mch_id = mch_id;            queryorder.transaction_id = res.GetValue("transaction_id").ToString();            queryorder.out_trade_no = "";            queryorder.nonce_str = TenpayUtil.getNoncestr();            TenpayUtil tenpay = new TenpayUtil();            OrderDetail orderdeatil = tenpay.getOrderDetail(queryorder, paySignKey);            //写微信记录            (new vinson()).WriteReturnWXDetail(orderdeatil);            //写充值记录            FilliedOnline(orderdeatil.out_trade_no);        }        Response.Write(res.ToXml());        Response.End();    }

扫码支付成功后会异步到这个页面执行代码,我们自己的业务逻辑就要写在这里。使用微信官方的ProcessNotify()函数可不行,我们稍微修改下就好了。增加ProcessNotify2函数:

 

public WxPayData ProcessNotify2()        {            WxPayData notifyData = GetNotifyData();            //检查支付结果中transaction_id是否存在            if (!notifyData.IsSet("transaction_id"))            {                //若transaction_id不存在,则立即返回结果给微信支付后台                WxPayData res = new WxPayData();                res.SetValue("transaction_id", "");                res.SetValue("return_code", "FAIL");                res.SetValue("return_msg", "支付结果中微信订单号不存在");                return res;            }            string transaction_id = notifyData.GetValue("transaction_id").ToString();            //查询订单,判断订单真实性            if (!QueryOrder(transaction_id))            {                //若订单查询失败,则立即返回结果给微信支付后台                WxPayData res = new WxPayData();                res.SetValue("transaction_id", transaction_id);                res.SetValue("return_code", "FAIL");                res.SetValue("return_msg", "订单查询失败");                return res;            }            //查询订单成功            else            {                WxPayData res = new WxPayData();                res.SetValue("transaction_id", transaction_id);                res.SetValue("return_code", "SUCCESS");                res.SetValue("return_msg", "OK");                return res;            }        }

 

返回WxPayData对象,这样一判断

if (res.GetValue("return_code") == "SUCCESS")
表示支付成功,就可以进入我们的业务逻辑。

 

然后我们还要对当前订单查单,获取订单的相关信息,之前微信未出demo的时候我自己写了个查单的,就直接用了,关键WxPayData对象会返回微信的订单号:res.GetValue("transaction_id").ToString()。

完事后还要发送信息回给微信,通知微信后台不要继续发送异步请求了:

 

        Response.Write(res.ToXml());        Response.End();

 

这个代码比较重要了。

再说说放置二维码的页面:

<div class="g-body">    <div class="g-wrap">        <div class="m-weixin">            <div class="m-weixin-header">                <p><strong>请您及时付款,以便订单尽快处理!订单号:<asp:Label ID="trade_no" runat="server" Text="Label"></asp:Label></strong></p>                <p>请您在提交订单后1小时内支付,否则订单会自动取消。</p>            </div>            <div class="m-weixin-main">                <h1 class="m-weixin-title">                    <img alt="微信支付" src="../images/wxlogo_pay.png"/>                </h1>                <p class="m-weixin-money"><font>扫一扫付款</font><br/><strong><asp:Label ID="money" runat="server" Text="Label"></asp:Label></strong></p>                <p>                    <img id="payQRImg" width="260" height="260" class="m-weixin-code" style="position: absolute;" src="<%=ImageUrl %>" alt="二维码" style="border-width:0px;" />                    <img class="m-weixin-demo" src="../images/wxwebpay_guide.png" alt="扫一扫" />                    <img style="margin-top:300px;" src="../images/weixin_1.png" alt="请使用微信扫描二维码以完成支付" />                </p>                <p id="we_ok" style="display:none;">                    <input value="完成" style="width: 300px; height: 50px; background: rgb(21, 164, 21) none repeat scroll 0% 0%; color: white; font-size: 30px; border: medium none; cursor: pointer;" type="button" />                </p>            </div>        </div>    </div></div>   

写个js查单支付情况进行显示:

    $(function () {        var success = "<%=success %>";        if (success == "error") {            $(".g-body").hide();        }    })    var iCount = setInterval(check, 2000);  //每隔2秒执行一次check函数。    function check() {        $.ajax({            contentType: "application/json",            url: "/WebService/vinson.asmx/queryWeiXin",            data: "{OrderID:‘" + $("#trade_no").text() + "‘}",            type: "POST",            dataType: "json",            success: function (json) {                json = eval("(" + json.d + ")");                if (json.success == "success") {                    clearInterval(iCount);                    $(".m-weixin-money font").html("已成功付款");                    $("#payQRImg").remove();                    $(".m-weixin-demo").before(‘<img  src="../images/wx_ok.jpg" width="200">‘);                    $(".m-weixin-demo").next().remove();                    $("#we_ok").show();                }            },            error: function (err, ex) {            }        });    }

是的,我又写了个给ajax使用的查单函数queryWeiXin。

我这里才是生成订单和二维码:

技术分享

恩,还有啥呢,恩,看看效果吧:

技术分享

支付成功后:

技术分享

恩,完事。

0 0
原创粉丝点击