zoukankan      html  css  js  c++  java
  • C#微信支付对接

     

    主要代码:

    复制代码
    /**
            * 生成直接支付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-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=" 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 alt="" src="../images/wx_ok.jpg" width="200">');
                        $(".m-weixin-demo").next().remove();
                        $("#we_ok").show();
                    }
                },
                error: function (err, ex) {
                }
            });
        }
    复制代码

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

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

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

    支付成功后:

    恩,完事。

  • 相关阅读:
    严重: Parse error in application web.xml file at jndi:/localhost/ipws/WEBINF/web.xml java.lang.NoSuchMethodException: org.apache.catalina.deploy.WebXml
    Failed to install .apk on device 'emulator5554': timeout解决方法
    java.lang.NoClassDefFoundError:org.jsoup.Jsoup
    Conversion to Dalvik format failed: Unable to execute dex:解决方法
    apache Digest: generating secret for digest authentication ...
    Description Resource Path Location Type Project has no default.properties file! Edit the project properties to set one.
    android service随机自启动
    MVC3 安装部署
    EF 4.3 CodeBased 数据迁移演练
    SQL Server 2008开启sa账户
  • 原文地址:https://www.cnblogs.com/zoujinhua/p/10384080.html
Copyright © 2011-2022 走看看