C#微信支付统一下单 APP支付接口

 的说微信支付是坑  官方demo 少不说 配置也恶心  的确 坑了我一个多星期 终于搞定了 给大家分享下我是怎么做出来的 让新手少走弯路,

 和大家一样接到要做这个功能我就开始各种百度找demo  也找了不少 但是拿来的没办法用 代码的没有问题 原因到底在哪里呢?

1、微信支付 统一下单接口 需要配置 MchId 商户号 AppId开发者平台去找 ApiKey 密钥 商户平台需要你自己去配置 NotifyUrl就是你的回调地址了 支付成功一样微信通知地址 

2、下面我来讲讲 微信的第一坑 AppId 很多人会吧 AppId 配置成公众平台的 AppId 其实不是,这里的APPID 是开放平台的, 也就是在公众平台开通APP 支付需要进入的平台

第二坑 packageStr  这个东西必须要加上 Sign=WXPay 

第三坑  也是最主要的坑, 就是签名 和包名 很多人 尤其是搞微信APP 开发的  他们会吧 他们打包上线用到的签名给你 然后让你和包名配置到你的开发平台里面去,最后结果不用说 肯定是支付不成功的,

这里的配置 很重要 让搞APP 开发的人 把 这个配置弄好 给开发后台的 别跟小白一样 以为什么东西的需要后台来做 这点我要鄙视那些 拿到数据就显示的APP 开发人员   这个功能生成出来的才是支付要的签名 下载地址和配置方式如下  

https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5 

把 这些工作做完了 现在我们看代码 下面的代码  本人亲自 测试完全没问题 直接可以用 只要你的上面的配置没问题 

不会的可以加我QQ 987707681  基本备注下你是干什么的 

public class pay
    {
        private string WeiXinPayUrl = ""; 支付完成通知地址
        private string packageStr = "Sign=WXPay";
        /// <summary>
        /// 微信支付商户号(从微信发给你的邮件中获得的)
        /// </summary>
        public string MchId
        {
            get;
            internal set;
        }
        /// <summary>
        /// 应用的APPID(微信发给你的邮件中也有这项内容,一般以wx开头,微信开放平台-管理中心-应用详情也可以看到这项内容)
        /// </summary>
        public string AppId
        {
            get;
            internal set;
        }
        /// <summary>
        /// 这里是API密钥,不是Appsecret,这里最容易出错了!请务必注意!
        /// 设置方法:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置
        /// </summary>
        public string ApiKey
        {
            get;
            internal set;
        }
        /// <summary>
        /// 支付成功后,微信会请求这个路径,
        /// </summary>
        public string NotifyUrl
        {
            get;
            internal set;
        }
        /// <summary>
        /// 支付类构造函数,三个关键参数缺一不可,均不能为空
        /// </summary>
        /// <param name="MchId">微信支付商户号(从微信发给你的邮件中获得的)</param>
        /// <param name="AppId">应用的APPID(微信发给你的邮件中也有这项内容,一般以wx开头,微信开放平台-管理中心-应用详情也可以看到这项内容)</param>
        /// <param name="ApiKey">
        /// 这里是API密钥,不是Appsecret,这里最容易出错了!请务必注意!
        /// 设置方法:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置
        /// </param>
        public pay(string MchId, string AppId, string ApiKey, string NotifyUrl)
        {
            this.MchId = MchId;
            this.AppId = AppId;
            this.ApiKey = ApiKey;
            this.NotifyUrl = NotifyUrl;
        }
        /// <summary>
        /// 开发发起支付
        /// </summary>
        /// <param name="TotalFee">总金额,单位:分,不能为空</param>
        /// <param name="TradeNo">订单号,你自己定就好了,不要重复,不能为空</param>
        /// <param name="Des">订单描述,不能为空</param>
        /// <param name="ClientIp">客户端的IP地址,不能为空</param>
        /// <param name="FeeType">货币类型,默认是CNY,人民币</param>
        /// <returns></returns>
        public string Pay(Int64 TotalFee, string TradeNo, string Des, string ClientIp, string FeeType = "CNY")
        {
            //为发送请求给微信服务器准备数据
            var nstr = MakeNonceStr();
            Hashtable packageParameter = new Hashtable();
            packageParameter.Add("appid", this.AppId);
            packageParameter.Add("body", Des);
            packageParameter.Add("mch_id", this.MchId);
            packageParameter.Add("notify_url", this.NotifyUrl);
            packageParameter.Add("nonce_str", nstr);
            packageParameter.Add("out_trade_no", TradeNo);
            packageParameter.Add("total_fee", TotalFee.ToString());
            packageParameter.Add("spbill_create_ip", ClientIp);
            packageParameter.Add("trade_type", "APP");
            packageParameter.Add("fee_type", FeeType);
            var sign = CreateMd5Sign(packageParameter);
            packageParameter.Add("sign", sign);
            var xe = PostDataToWeiXin(packageParameter);
            //为响应客户端的请求准备数据 
            var timeStamp = GetTimeStamp();
            var prepayId = xe.Element("prepay_id").Value;
            nstr = xe.Element("nonce_str").Value;
            Hashtable paySignReqHandler = new Hashtable();
            paySignReqHandler.Add("appid", this.AppId);
            paySignReqHandler.Add("partnerid", this.MchId);
            paySignReqHandler.Add("prepayid", prepayId);
            paySignReqHandler.Add("noncestr", nstr);
            paySignReqHandler.Add("package", packageStr);
            paySignReqHandler.Add("timestamp", timeStamp.ToString());
            var paySign = CreateMd5Sign(paySignReqHandler);
            var obj = new
            {
                appid = this.AppId,
                partnerid = this.MchId,
                prepayid = prepayId,
                package = packageStr,
                noncestr = nstr,
                timestamp = timeStamp,
                sign = paySign
            };
            var serializer = new JavaScriptSerializer();
            var result = serializer.Serialize(obj);
            return result;
        }
        public static string GetTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }
        private XElement PostDataToWeiXin(Hashtable parameters)
        {
            var xmlStr = getXmlStr(parameters);
            var data = Encoding.UTF8.GetBytes(xmlStr);
            Stream responseStream;
            HttpWebRequest request = WebRequest.Create(WeiXinPayUrl) as HttpWebRequest;
            request.ContentType = "application/x-www-form-urlencoded";
            request.Method = "POST";
            request.ContentLength = data.Length;
            Stream requestStream = request.GetRequestStream();
            requestStream.Write(data, 0, data.Length);
            requestStream.Close();
            try
            {
                responseStream = request.GetResponse().GetResponseStream();
            }
            catch (Exception exception)
            {
                throw exception;
            }
            string str = string.Empty;
            using (StreamReader reader = new StreamReader(responseStream, Encoding.UTF8))
            {
                str = reader.ReadToEnd();
            }
            responseStream.Close();
            var xe = XElement.Parse(str);
            return xe;
        }


        private string getXmlStr(Hashtable parameters)
        {
            var sb = new StringBuilder();
            sb.Append("<xml>");
            foreach (string k in parameters.Keys)
            {
                var v = (string)parameters[k];
                if (Regex.IsMatch(v, @"^[0-9.]$"))
                {
                    sb.Append("<" + k + ">" + v + "</" + k + ">");
                }
                else
                {
                    sb.Append("<" + k + "><![CDATA[" + v + "]]></" + k + ">");
                }
            }
            sb.Append("</xml>");
            return sb.ToString();
        }
        private string CreateMd5Sign(Hashtable parameters)
        {
            var sb = new StringBuilder();
            var akeys = new ArrayList(parameters.Keys);
            akeys.Sort();//排序,这是微信要求的
            foreach (string k in akeys)
            {
                var v = (string)parameters[k];
                sb.Append(k + "=" + v + "&");
            }
            sb.Append("key=" + ApiKey);
            string sign = GetMD5(sb.ToString());
            return sign;
        }


        private string MakeNonceStr()
        {
            var timestap = DateTime.Now.ToString("yyyyMMddhhmmssffff");
            return GetMD5(timestap);
        }
        private string GetMD5(string src)
        {
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] data = Encoding.UTF8.GetBytes(src);
            byte[] md5data = md5.ComputeHash(data);
            md5.Clear();
            var retStr = BitConverter.ToString(md5data);
            retStr = retStr.Replace("-", "").ToUpper();
            return retStr;
        }
    }

下面是接口的发起代码 下面这几个参数记得配置好 而且不能错 

            string MchId = ""; 商户号
            string AppId = ""; 开发者平台的AppId不是公众平台的 记住咯 
            string ApiKey = ""; 商户平台自己配置的密钥 
            string NotifyUrl = ""; 支付成功公众地址 

            // 把这些全部配置好一会 出问题 就是APP 签名的问题了   
            var payment = new pay(MchId,
                AppId,
                ApiKey,
                NotifyUrl);
            string Amount = Request.QueryString["Amount"];
            Int64 wx_total_fee = Int64.Parse(Request.QueryString["wxtotalfee"]);
            var orderId = Request.QueryString["orderid"];
            var jsonStr = payment.Pay(wx_total_fee, orderId, ""+ Amount + "", Page.Request.UserHostAddress);
            Response.Write(jsonStr);

好吧 我在做次好人 我吧通知地址 也提供给大家 很多人 可能的不知道 NotifyUrl 大家拿去自己建 一个类 复制进去就可以用了 LogUtil.WriteLog 是我用来做日志用的 大家拿去可能会报错 直接注释掉就行 

           //创建ResponseHandler实例
            ResponseHandler resHandler = new ResponseHandler(Context);
            string ApiKey = ""; 商户平台的 密钥 记得配合 
            resHandler.setKey(ApiKey);
            //判断签名
            try
            {
                string error = "";
                if (resHandler.isWXsign(out error))
                {
                    #region 协议参数=====================================
                    //--------------协议参数--------------------------------------------------------
                    //SUCCESS/FAIL此字段是通信标识,非交易标识,交易是否成功需要查
                    string return_code = resHandler.getParameter("return_code");
                    //返回信息,如非空,为错误原因签名失败参数格式校验错误
                    string return_msg = resHandler.getParameter("return_msg");
                    //微信分配的公众账号 ID
                    string appid = resHandler.getParameter("appid");


                    //以下字段在 return_code 为 SUCCESS 的时候有返回--------------------------------
                    //微信支付分配的商户号
                    string mch_id = resHandler.getParameter("mch_id");
                    //微信支付分配的终端设备号
                    string device_info = resHandler.getParameter("device_info");
                    //微信分配的公众账号 ID
                    string nonce_str = resHandler.getParameter("nonce_str");
                    //业务结果 SUCCESS/FAIL
                    string result_code = resHandler.getParameter("result_code");
                    //错误代码 
                    string err_code = resHandler.getParameter("err_code");
                    //结果信息描述
                    string err_code_des = resHandler.getParameter("err_code_des");


                    //以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回---------------
                    //-------------业务参数---------------------------------------------------------
                    //用户在商户 appid 下的唯一标识
                    string openid = resHandler.getParameter("openid");
                    //用户是否关注公众账号,Y-关注,N-未关注,仅在公众账号类型支付有效
                    string is_subscribe = resHandler.getParameter("is_subscribe");
                    //JSAPI、NATIVE、MICROPAY、APP
                    string trade_type = resHandler.getParameter("trade_type");
                    //银行类型,采用字符串类型的银行标识
                    string bank_type = resHandler.getParameter("bank_type");
                    //订单总金额,单位为分
                    string total_fee = resHandler.getParameter("total_fee");
                    //货币类型,符合 ISO 4217 标准的三位字母代码,默认人民币:CNY
                    string fee_type = resHandler.getParameter("fee_type");
                    //微信支付订单号
                    string transaction_id = resHandler.getParameter("transaction_id");
                    //商户系统的订单号,与请求一致。
                    string out_trade_no = resHandler.getParameter("out_trade_no");
                    //商家数据包,原样返回
                    string attach = resHandler.getParameter("attach");
                    //支 付 完 成 时 间 , 格 式 为yyyyMMddhhmmss,如 2009 年12 月27日 9点 10分 10 秒表示为 20091227091010。时区为 GMT+8 beijing。该时间取自微信支付服务器
                    string time_end = resHandler.getParameter("time_end");
                    #endregion
                    //支付成功
                    if (!out_trade_no.Equals("") && return_code.Equals("SUCCESS") && result_code.Equals("SUCCESS"))
                    {
                        Response.Write("success");
                        LogUtil.WriteLog("Notify 页面  支付成功,支付信息:商家订单号:" + out_trade_no + "、支付金额(分):" + total_fee + "、自定义参数:" + attach);
                        LogUtil.WriteLog("============ 单次支付结束 ===============");
                        return;
                    }
                    else
                    {
                        LogUtil.WriteLog("Notify 页面  支付失败,支付信息   total_fee= " + total_fee + "、err_code_des=" + err_code_des + "、result_code=" + result_code);
                    }
                }
                else
                {
                    LogUtil.WriteLog("Notify 页面  isWXsign= false ,错误信息:" + error);
                }
            catch (Exception ee)
            {
                LogUtil.WriteLog("Notify 页面  发送异常错误:" + ee.Message);
            }
            Response.End();

        }

如果有看不懂的 我在csdn 上放了完整demo  下载地址 https://download.csdn.net/download/hejianxiong520/10189747

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值