C# 微信(小程序)支付

简单的实现了小程序支付,对应的api接口.

using Senparc.CO2NET.Cache;
using Senparc.CO2NET.Helpers;
using Senparc.CO2NET.Utilities;
using Senparc.Weixin;
using Senparc.Weixin.Exceptions;
using Senparc.Weixin.TenPay;
using Senparc.Weixin.TenPay.V3;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Mvc;
using System.Xml;
using System.Xml.Linq;

namespace WiseCarAPI.Controllers
{
    public class wxPayController : Controller
    {
     
        public ActionResult pay(string jscode, string fee)
        {
            bool bosucceed = true;
            try
            {
                string _posdata = "appid=" + appid + "&secret=" + secret + "&js_code=" + jscode + "&grant_type=authorization_code";
                string _url = "https://api.weixin.qq.com/sns/jscode2session";//获取openid
                string _data = request_url(_url, _posdata);
                if (_data.Contains("\"openid\""))
                {

                    string _ip = Request.ServerVariables.Get("Remote_Addr").ToString().Trim();
                    dynamic _modal = Newtonsoft.Json.Linq.JToken.Parse(_data) as dynamic;
                    string _openid = _modal.openid;
                    //--------以上获取openid--end,--以下获取prepay_id--begin
                    #region 获取prepay_id 
                    string _nonce_str = get_nonce_str();

                    string timeStamp = getTimeStamp();
                    string _out_trade_no = DateTime.Now.ToString("yyMMddHHmmssfff" + new Random(1000).Next().ToString());//  DateTime.Now.ToString("yyMMddHHmmssfff") + GetRand(1, 20).ToString();//get_nonce_str();
                    Dictionary datalist = new Dictionary();
                    datalist.Add("appid", appid);
                    datalist.Add("mch_id", mch_id);
                    datalist.Add("nonce_str", _nonce_str);
                    datalist.Add("body", "test");
                    //datalist.Add("detail", "{\"goods_detail\":[ { \"goods_id\":\"iphone6s_16G\", \"wxpay_goods_id\":\"1001\", \"goods_name\":\"iPhone6s 16G\", \"quantity\":1, \"price\":528800, \"goods_category\":\"123456\", \"body\":\"苹果手机\" }] }>");
                    datalist.Add("out_trade_no", _out_trade_no);
                    datalist.Add("total_fee", fee);
                    datalist.Add("spbill_create_ip", _ip);
                    datalist.Add("notify_url", notify_url);
                    datalist.Add("trade_type", "JSAPI");
                    datalist.Add("openid", _openid);
                    //排序datalist
                    string _sign = getParamSrc(datalist);//CreateMd5Sign
                    datalist.Add("sign", _sign);
                    //将datalist将成xml
                    string xml = getRequestXml(datalist);//ParseXML
                    StringBuilder str = new StringBuilder();

                    _url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
                    _data = request_url(_url, xml);//获取prepay_id
                    #endregion
                    #region  解析返回的xml,求paySign
                    Dictionary dirxml = (getdata_fromxml(_data));
                    //txt_Result.Text += "\n" + _data;
                    bool boGet_prepay_id = false;
                    string _prepay_id = "";
                    if (dirxml.ContainsKey("return_code"))
                    {
                        if (dirxml["return_code"].ToString().ToUpper() == "SUCCESS")
                        {
                            _prepay_id = dirxml["prepay_id"].Trim();
                            boGet_prepay_id = true;
                        }
                    }
                    if (boGet_prepay_id)
                    {

                        string _paySign = "appId=" + appid;
                        _paySign += "&nonceStr=" + _nonce_str;
                        _paySign += "&package=prepay_id=" + _prepay_id;
                        string _timeStamp = timeStamp;
                        _paySign += "&signType=MD5&timeStamp=" + _timeStamp + "&key=" + key;

                        string paySign = UserMd5(_paySign);

                        return this.Json(new { succeed = true, data = "成功", timeStamp = _timeStamp, nonceStr = _nonce_str, package = "prepay_id=" + _prepay_id, paySign = paySign, notify_url = notify_url }, JsonRequestBehavior.AllowGet);

                    }
                    else
                    {
                        return this.Json(new { succeed = false, data = "获取prepay_id失败" }, JsonRequestBehavior.AllowGet);
                    }
                    #endregion
                }
                else
                {
                    return this.Json(new { succeed = false, data = "获取openid失败" }, JsonRequestBehavior.AllowGet);
                }
            }
            catch (Exception ex)
            {
                return this.Json(new { succeed = false, data = ex.Message }, JsonRequestBehavior.AllowGet);
            }

        }

          
       

        #region paytest
        ///


        /// 随机生成Noncestr
        ///

        ///
        public string GetNoncestr()
        {
            return EncryptHelper.GetMD5(Guid.NewGuid().ToString(), "UTF-8");
        }
        ///
        /// 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名
        ///

        /// 参数名
        /// 参数值
        /// key和value通常用于填充最后一组参数
        ///
        public string CreateMd5Sign(string key, string value, Hashtable Parameters)
        {
            StringBuilder sb = new StringBuilder();

            ArrayList akeys = new ArrayList(Parameters.Keys);
            akeys.Sort(ASCIISort.Create());

            foreach (string k in akeys)
            {
                string v = (string)Parameters[k];
                if (null != v && "".CompareTo(v) != 0
                    && "sign".CompareTo(k) != 0
                    //&& "sign_type".CompareTo(k) != 0
                    && "key".CompareTo(k) != 0)
                {
                    sb.Append(k + "=" + v + "&");
                }
            }

            sb.Append(key + "=" + value);

            //string sign = EncryptHelper.GetMD5(sb.ToString(), GetCharset()).ToUpper();
            //using Senparc.CO2NET.Helpers;
            //编码强制使用UTF8:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_1
            string sign = EncryptHelper.GetMD5(sb.ToString(), "UTF-8").ToUpper();

            return sign;
        }

        ///


        /// 输出XML
        ///

        ///
        public string ParseXML(Hashtable Parameters)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("");
            foreach (string k in Parameters.Keys)
            {
                string v = (string)Parameters[k];
                if (v != null && Regex.IsMatch(v, @"^[0-9.]$"))
                {

                    sb.Append("<" + k + ">" + v + "");
                }
                else
                {
                    sb.Append("<" + k + ">");
                }
            }
            sb.Append("");
            return sb.ToString();
        }
        #endregion

        #region 回调函数
        ///


        /// 回调函数
        ///

        ///
        public ActionResult notifyurl()
        {
            try
            {

                Hashtable has = new Hashtable();
                System.Collections.Specialized.NameValueCollection collection;
                if (this.HttpContext.Request.HttpMethod.ToUpper() == "POST")
                {
                    collection = this.HttpContext.Request.Form;
                    foreach (string k in collection)
                    {
                        string v = (string)collection[k];
                        has.Add(k, v);
                    }
                }
                collection = this.HttpContext.Request.QueryString;
                foreach (string k in collection)
                {
                    string v = (string)collection[k];
                    has.Add(k, v);
                }
                if (this.HttpContext.Request.InputStream.Length > 0)
                {
                    XmlDocument xmlDoc = new XmlDocument();
                    xmlDoc.Load(this.HttpContext.Request.InputStream);
                    XmlNode root = xmlDoc.SelectSingleNode("xml");
                    XmlNodeList xnl = root.ChildNodes;

                    foreach (XmlNode xnf in xnl)
                    {
                        has.Add(xnf.Name, xnf.InnerText);
                    }
                }


                string _xml = ParseXML(has);

                 Savelog(_xml);
                //string temv = msg;
                return this.Json(new
                {
                    succeed = true,
                    data = _xml

                }, JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                return this.Json(new
                {
                    succeed = false,
                    data = ex.Message
                }, JsonRequestBehavior.AllowGet);
            }
        }
        ///


        /// 保存日志文件
        ///

        ///
        private void Savelog(string saveinfo)
        {
            try
            {

                var logDir = Server.MapPath(string.Format("~/App_Data/TenPayNotify/{0}", SystemTime.Now.ToString("yyyyMMdd")));
                if (!Directory.Exists(logDir))
                {
                    Directory.CreateDirectory(logDir);
                }
                var logpath = Path.Combine(logDir, DateTime.Now.ToString("yyMMdd") + ".log");
                using (var fileStream = System.IO.File.OpenWrite(logpath))
                {
                    fileStream.Write(Encoding.Default.GetBytes(saveinfo), 0, Encoding.Default.GetByteCount(saveinfo));
                    fileStream.Close();
                }

            }
            catch (Exception ex)
            {

            }
        }
        #endregion

      

        #region  相关参数及方法
         region 微信参数

        string appid
        {
            get
            {
                string temV = System.Configuration.ConfigurationManager.AppSettings["appid"].Trim();
                return temV;
            }
        }
        string secret
        {
            get
            {
                string temV = System.Configuration.ConfigurationManager.AppSettings["secret"].Trim();
                return temV;
            }
        }
        string mch_id
        {
            get
            {
                string temV = System.Configuration.ConfigurationManager.AppSettings["mch_id"].Trim();
               return temV;
            }
        }
        string notify_url
        {
            get
            {
                string temV = System.Configuration.ConfigurationManager.AppSettings["notify_url"].Trim();
                return temV;
            }
        }
        string key
        {
            get
            {
                string temV = System.Configuration.ConfigurationManager.AppSettings["key"].Trim();
                 return temV;
            }
        }
        #endregion

        #region 获取随机字符串
        ///


        /// 获取随机字符串
        ///

        ///
        private string get_nonce_str()
        {
            string result = DateTime.Now.ToString("yyyMMddHHmmssfff");
            System.Random rand = new Random();
            string _strKey = "QWERTYUIOPASDFGHJKLZXVBNMqwertyuioplkjhgfdsamnbvcxz";
            while (result.Length < 32)
            {
                int _index = rand.Next(1, _strKey.Length - 1);
                result += _strKey.Substring(_index, 1);
            }
            return result;
        }
        #endregion

        #region 获取当前时间的时间戳
        ///


                /// 获取当前时间的时间戳
                ///

                /// 时间戳的string格式
        string getTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }
        ///
        /// 获取一定范围内的任意随机数
        ///

        /// 最小范围
        /// 最大范围
        /// 随机数
        string GetRand(int minValue, int MaxValue)
        {
            Random rd = new Random();
            return rd.Next(minValue, MaxValue).ToString();
        }
        #endregion

        #region 32位MD5加密
        ///


        /// 32位MD5加密
        ///

        ///
        ///
        public string UserMd5(string str)
        {
            //using System.Security;
            string cl = str;
            string str_md5 = "";
            MD5 md5 = MD5.Create();//实例化一个md5对像
            // 加密后是一个字节类型的数组,这里要注意编码UTF8/Unicode等的选择 
            byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(cl));
            // 通过使用循环,将字节类型的数组转换为字符串,此字符串是常规字符格式化所得
            for (int i = 0; i < s.Length; i++)
            {
                // 将得到的字符串使用十六进制类型格式。格式后的字符是小写的字母,如果使用大写(X)则格式后的字符是大写字符 
                str_md5 = str_md5 + s[i].ToString("x2");

            }
            return str_md5;
        }
        #endregion

        #region 解析xml字符串
        ///


        /// 解析xml字符串
        ///

        ///
        ///
        private Dictionary getdata_fromxml(string xml)
        {
            Dictionary d_value = new Dictionary();
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(xml);
            XmlNode rootNode = xmlDoc.SelectSingleNode("xml");
            foreach (XmlNode xxNode in rootNode.ChildNodes)
            {
                string dsf = xxNode.InnerText;
                string sdf = xxNode.Name;
                d_value.Add(xxNode.Name, xxNode.InnerText);
            }
            return d_value;
        }
        #endregion

        #region 对参数按照key=value的格式,并按照参数名ASCII字典序排序,同时求sign
        ///


        /// 对参数按照key=value的格式,并按照参数名ASCII字典序排序,同时求sign
        ///

        ///
        ///
        public String getParamSrc(Dictionary paramsMap)
        {
            var vDic = (from objDic in paramsMap orderby objDic.Key ascending select objDic);
            StringBuilder str = new StringBuilder();
            foreach (KeyValuePair kv in vDic)
            {
                string pkey = kv.Key;
                string pvalue = kv.Value;
                str.Append(pkey + "=" + pvalue + "&");
            }

            String result = str.ToString().Substring(0, str.ToString().Length - 1);
            result += "&key=" + key;
            string temV = UserMd5(result);
            return temV;
        }
        #endregion

        #region 将Dictionary转成xml
        ///


        /// 将Dictionary转成xml
        ///

        ///
        ///
        public String getRequestXml(Dictionary parameters)
        {

            StringBuilder sb = new StringBuilder();
            sb.Append("");
            foreach (KeyValuePair e in parameters)
            {
                string k = e.Key.ToString().Trim();
                string v = e.Value.ToString().Trim();
                if (v != null && Regex.IsMatch(v, @"^[0-9.]$"))
                {
                    //{
                    sb.AppendLine("<" + k + ">" + v + "");
                }
                else
                {
                    sb.Append("<" + k + ">" + "");
                }
            }
            sb.Append("
");
            return sb.ToString();
        }
        #endregion

        #region 请求api
        ///


        /// 请求api
        ///

        ///
        ///
        ///
        private string request_url(string _url, string post_data)
        {
            string result = "";
            // https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code

            string url = _url;// "https://api.weixin.qq.com/sns/jscode2session";
            Encoding encoding = Encoding.UTF8;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.ContentType = "application/json";
            //request.Headers=""
            request.Method = "POST";

            byte[] buffer = encoding.GetBytes(post_data.Trim());
            request.ContentLength = buffer.Length;
            request.GetRequestStream().Write(buffer, 0, buffer.Length);

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
            {
                result = reader.ReadToEnd();
            }
            return result;
        }
        #endregion
        #endregion


    }
}

你可能感兴趣的:(C# 微信(小程序)支付)