Beispiel #1
0
        /**
         *
         * 查询订单
         * @param WxPayData inputObj 提交给查询订单API的参数
         * @param int timeOut 超时时间
         * @throws WxPayException
         * @return 成功时返回订单查询结果,其他抛异常
         */

        public static WxPayData OrderQuery(WxPayData inputObj, int timeOut = 6)
        {
            string url = "https://api.mch.weixin.qq.com/pay/orderquery";

            //检测必填参数
            if (!inputObj.IsSet("out_trade_no") && !inputObj.IsSet("transaction_id"))
            {
                throw new WxPayException("订单查询接口中,out_trade_no、transaction_id至少填一个!");
            }

            JsApiConfig jsApiConfig = new JsApiConfig();

            inputObj.SetValue("appid", jsApiConfig.AppId);               //公众账号ID
            inputObj.SetValue("mch_id", jsApiConfig.Partner);            //商户号
            inputObj.SetValue("nonce_str", WxPayApi.GenerateNonceStr()); //随机字符串
            inputObj.SetValue("sign", inputObj.MakeSign());              //签名

            string xml = inputObj.ToXml();

            var start = DateTime.Now;

            string response = HttpService.Post(xml, url, false, timeOut);//调用HTTP通信接口提交数据

            var end      = DateTime.Now;
            int timeCost = (int)((end - start).TotalMilliseconds);//获得接口耗时

            //将xml格式的数据转化为对象以返回
            WxPayData result = new WxPayData();

            result.FromXml(response);

            ReportCostTime(url, timeCost, result);//测速上报

            return(result);
        }
Beispiel #2
0
        /**
         *
         * 撤销订单API接口
         * @param WxPayData inputObj 提交给撤销订单API接口的参数,out_trade_no和transaction_id必填一个
         * @param int timeOut 接口超时时间
         * @throws WxPayException
         * @return 成功时返回API调用结果,其他抛异常
         */

        public static WxPayData Reverse(WxPayData inputObj, int timeOut = 6)
        {
            string url = "https://api.mch.weixin.qq.com/secapi/pay/reverse";

            //检测必填参数
            if (!inputObj.IsSet("out_trade_no") && !inputObj.IsSet("transaction_id"))
            {
                throw new WxPayException("撤销订单API接口中,参数out_trade_no和transaction_id必须填写一个!");
            }

            JsApiConfig jsApiConfig = new JsApiConfig();

            inputObj.SetValue("appid", jsApiConfig.AppId);      //公众账号ID
            inputObj.SetValue("mch_id", jsApiConfig.Partner);   //商户号
            inputObj.SetValue("nonce_str", GenerateNonceStr()); //随机字符串
            inputObj.SetValue("sign", inputObj.MakeSign());     //签名
            string xml = inputObj.ToXml();

            var start = DateTime.Now;//请求开始时间

            string response = HttpService.Post(xml, url, true, timeOut);

            var end      = DateTime.Now;
            int timeCost = (int)((end - start).TotalMilliseconds);

            WxPayData result = new WxPayData();

            result.FromXml(response);

            ReportCostTime(url, timeCost, result);//测速上报

            return(result);
        }
Beispiel #3
0
        /**
         *
         * 转换短链接
         * 该接口主要用于扫码原生支付模式一中的二维码链接转成短链接(weixin://wxpay/s/XXXXXX),
         * 减小二维码数据量,提升扫描速度和精确度。
         * @param WxPayData inputObj 提交给转换短连接API的参数
         * @param int timeOut 接口超时时间
         * @throws WxPayException
         * @return 成功时返回,其他抛异常
         */

        public static WxPayData ShortUrl(WxPayData inputObj, int timeOut = 6)
        {
            string url = "https://api.mch.weixin.qq.com/tools/shorturl";

            //检测必填参数
            if (!inputObj.IsSet("long_url"))
            {
                throw new WxPayException("需要转换的URL,签名用原串,传输需URL encode!");
            }

            JsApiConfig jsApiConfig = new JsApiConfig();

            inputObj.SetValue("appid", jsApiConfig.AppId);      //公众账号ID
            inputObj.SetValue("mch_id", jsApiConfig.Partner);   //商户号
            inputObj.SetValue("nonce_str", GenerateNonceStr()); //随机字符串
            inputObj.SetValue("sign", inputObj.MakeSign());     //签名
            string xml = inputObj.ToXml();

            var start = DateTime.Now;//请求开始时间

            string response = HttpService.Post(xml, url, false, timeOut);

            var end      = DateTime.Now;
            int timeCost = (int)((end - start).TotalMilliseconds);

            WxPayData result = new WxPayData();

            result.FromXml(response);
            ReportCostTime(url, timeCost, result);//测速上报

            return(result);
        }
Beispiel #4
0
        /**
         *
         * 申请退款
         * @param WxPayData inputObj 提交给申请退款API的参数
         * @param int timeOut 超时时间
         * @throws WxPayException
         * @return 成功时返回接口调用结果,其他抛异常
         */

        public static WxPayData Refund(WxPayData inputObj, int timeOut = 6)
        {
            string url = "https://api.mch.weixin.qq.com/secapi/pay/refund";

            //检测必填参数
            if (!inputObj.IsSet("out_trade_no") && !inputObj.IsSet("transaction_id"))
            {
                throw new WxPayException("退款申请接口中,out_trade_no、transaction_id至少填一个!");
            }
            else if (!inputObj.IsSet("out_refund_no"))
            {
                throw new WxPayException("退款申请接口中,缺少必填参数out_refund_no!");
            }
            else if (!inputObj.IsSet("total_fee"))
            {
                throw new WxPayException("退款申请接口中,缺少必填参数total_fee!");
            }
            else if (!inputObj.IsSet("refund_fee"))
            {
                throw new WxPayException("退款申请接口中,缺少必填参数refund_fee!");
            }
            else if (!inputObj.IsSet("op_user_id"))
            {
                throw new WxPayException("退款申请接口中,缺少必填参数op_user_id!");
            }

            JsApiConfig jsApiConfig = new JsApiConfig();

            inputObj.SetValue("appid", jsApiConfig.AppId);                              //公众账号ID
            inputObj.SetValue("mch_id", jsApiConfig.Partner);                           //商户号
            inputObj.SetValue("nonce_str", Guid.NewGuid().ToString().Replace("-", "")); //随机字符串
            inputObj.SetValue("sign", inputObj.MakeSign());                             //签名

            string xml   = inputObj.ToXml();
            var    start = DateTime.Now;

            string response = HttpService.Post(xml, url, true, timeOut);//调用HTTP通信接口提交数据到API

            var end      = DateTime.Now;
            int timeCost = (int)((end - start).TotalMilliseconds);//获得接口耗时

            //将xml格式的结果转换为对象以返回
            WxPayData result = new WxPayData();

            result.FromXml(response);

            ReportCostTime(url, timeCost, result);//测速上报

            return(result);
        }
Beispiel #5
0
        /**
         *
         * 测速上报接口实现
         * @param WxPayData inputObj 提交给测速上报接口的参数
         * @param int timeOut 测速上报接口超时时间
         * @throws WxPayException
         * @return 成功时返回测速上报接口返回的结果,其他抛异常
         */

        public static WxPayData Report(WxPayData inputObj, int timeOut = 1)
        {
            string url = "https://api.mch.weixin.qq.com/payitil/report";

            //检测必填参数
            if (!inputObj.IsSet("interface_url"))
            {
                throw new WxPayException("接口URL,缺少必填参数interface_url!");
            }
            if (!inputObj.IsSet("return_code"))
            {
                throw new WxPayException("返回状态码,缺少必填参数return_code!");
            }
            if (!inputObj.IsSet("result_code"))
            {
                throw new WxPayException("业务结果,缺少必填参数result_code!");
            }
            if (!inputObj.IsSet("user_ip"))
            {
                throw new WxPayException("访问接口IP,缺少必填参数user_ip!");
            }
            if (!inputObj.IsSet("execute_time_"))
            {
                throw new WxPayException("接口耗时,缺少必填参数execute_time_!");
            }

            JsApiConfig jsApiConfig = new JsApiConfig();

            inputObj.SetValue("appid", jsApiConfig.AppId);                      //公众账号ID
            inputObj.SetValue("mch_id", jsApiConfig.Partner);                   //商户号
            inputObj.SetValue("user_ip", ToolHelper.GetIP());                   //终端ip
            inputObj.SetValue("time", DateTime.Now.ToString("yyyyMMddHHmmss")); //商户上报时间
            inputObj.SetValue("nonce_str", GenerateNonceStr());                 //随机字符串
            inputObj.SetValue("sign", inputObj.MakeSign());                     //签名
            string xml = inputObj.ToXml();

            string response = HttpService.Post(xml, url, false, timeOut);

            WxPayData result = new WxPayData();

            result.FromXml(response);
            return(result);
        }
        /**
         * @生成签名,详见签名生成算法
         * @return 签名, sign字段不参加签名
         */

        public string MakeSign()
        {
            //转url格式
            string str = ToUrl();
            //在string后加入API KEY
            JsApiConfig jsApiConfig = new JsApiConfig();

            str += "&key=" + jsApiConfig.Key;
            //MD5加密
            var md5 = MD5.Create();
            var bs  = md5.ComputeHash(Encoding.UTF8.GetBytes(str));
            var sb  = new StringBuilder();

            foreach (byte b in bs)
            {
                sb.Append(b.ToString("x2"));
            }
            //所有字符转为大写
            return(sb.ToString().ToUpper());
        }
Beispiel #7
0
        /// <summary>
        /// 接收从微信支付后台发送过来的数据并验证签名
        /// </summary>
        /// <returns>微信支付后台返回的数据</returns>
        public static WxPayData GetNotifyData()
        {
            //接收从微信后台POST过来的数据
            System.IO.Stream s = HttpContext.Current.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();
            JsApiConfig jsApiConfig = new JsApiConfig();

            try
            {
                data.FromXml(builder.ToString());
            }
            catch (WxPayException ex)
            {
                //若签名错误,则立即返回结果给微信支付后台
                WxPayData res = new WxPayData();
                res.SetValue("return_code", "FAIL");
                res.SetValue("return_msg", ex.Message);
                HttpContext.Current.Response.Write(res.ToXml());
                HttpContext.Current.Response.End();
            }

            return(data);
        }
Beispiel #8
0
        /**
         * 下载对账单
         * @param WxPayData inputObj 提交给下载对账单API的参数
         * @param int timeOut 接口超时时间
         * @throws WxPayException
         * @return 成功时返回,其他抛异常
         */

        public static WxPayData DownloadBill(WxPayData inputObj, int timeOut = 6)
        {
            string url = "https://api.mch.weixin.qq.com/pay/downloadbill";

            //检测必填参数
            if (!inputObj.IsSet("bill_date"))
            {
                throw new WxPayException("对账单接口中,缺少必填参数bill_date!");
            }

            JsApiConfig jsApiConfig = new JsApiConfig();

            inputObj.SetValue("appid", jsApiConfig.AppId);      //公众账号ID
            inputObj.SetValue("mch_id", jsApiConfig.Partner);   //商户号
            inputObj.SetValue("nonce_str", GenerateNonceStr()); //随机字符串
            inputObj.SetValue("sign", inputObj.MakeSign());     //签名

            string xml = inputObj.ToXml();

            string response = HttpService.Post(xml, url, false, timeOut);//调用HTTP通信接口以提交数据到API

            WxPayData result = new WxPayData();

            //若接口调用失败会返回xml格式的结果
            if (response.Substring(0, 5) == "<xml>")
            {
                result.FromXml(response);
            }
            //接口调用成功则返回非xml格式的数据
            else
            {
                result.SetValue("result", response);
            }

            return(result);
        }
Beispiel #9
0
        public static async Task <WxPayData> GetJSSDKConfig()
        {
            JsApiConfig jsApiConfig = new JsApiConfig();

            string appid = jsApiConfig.AppId;

            string secret = jsApiConfig.AppSecret;

            string timestamp = WxPayApi.GenerateTimeStamp();

            string noncestr = WxPayApi.GenerateNonceStr();

            string signature = "";

            //签名算法  https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115

            //1. 获取AccessToken(有效期7200秒,开发者必须在自己的服务全局缓存access_token)

            WxTicketHelper helper = new WxTicketHelper();

            WxTicket wxticket = await helper.GetWxTicketAsync(WxTicketType.ACCESS_TOKEN);

            string access_token = string.Empty;

            if (wxticket == null || wxticket.ExpireTime < ConvertDateTimeInt(DateTime.Now))
            {
                string url1 = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret;

                string result = HttpService.Get(url1);

                JsonData jd = JsonMapper.ToObject(result);
                if (!((System.Collections.IDictionary)jd).Contains("access_token"))
                {
                    LogHelper.Error("access_token is null:" + result);
                    return(null);
                }
                access_token = (string)jd["access_token"];

                await helper.SaveAsync(WxTicketType.ACCESS_TOKEN, new WxTicket
                {
                    Ticket     = access_token,
                    ExpireTime = ConvertDateTimeInt(DateTime.Now) + 7180
                });
            }
            else
            {
                access_token = wxticket.Ticket;
            }

            //2. 用第一步拿到的access_token 采用http GET方式请求获得jsapi_ticket(有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket)
            wxticket = await helper.GetWxTicketAsync(WxTicketType.TICKET);

            string ticket = string.Empty;

            if (wxticket == null || wxticket.ExpireTime < ConvertDateTimeInt(DateTime.Now))
            {
                string url2 = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + access_token + "&type=jsapi";

                string result2 = HttpService.Get(url2);

                JsonData jd2 = JsonMapper.ToObject(result2);

                if (!((System.Collections.IDictionary)jd2).Contains("ticket"))
                {
                    return(null);
                }

                ticket = (string)jd2["ticket"];

                await helper.SaveAsync(WxTicketType.TICKET, new WxTicket
                {
                    Ticket     = ticket,
                    ExpireTime = ConvertDateTimeInt(DateTime.Now) + 7180
                });
            }
            else
            {
                ticket = wxticket.Ticket;
            }

            //3. 开始签名

            Uri    uri     = HttpContext.Current.Request.Url;
            string now_url = (uri.Scheme + "://" + uri.Host + HttpContext.Current.Request.RawUrl).Split('#')[0];

            string no_jiami = $"jsapi_ticket={ticket}&noncestr={noncestr}&timestamp={timestamp}&url={now_url}";

            //SHA1加密

            signature = SHA1_Hash(no_jiami);

            WxPayData data = new WxPayData();

            data.SetValue("appId", appid);

            data.SetValue("timestamp", timestamp);

            data.SetValue("nonceStr", noncestr);

            data.SetValue("signature", signature);

            return(data);
        }
Beispiel #10
0
        /**
         *
         * 统一下单
         * @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为必填参数!");
            }

            JsApiConfig jsApiConfig = new JsApiConfig();

            //异步通知url未设置,则使用配置文件中的url
            if (!inputObj.IsSet("notify_url"))
            {
                inputObj.SetValue("notify_url", jsApiConfig.Notify_url);//异步通知url
            }

            inputObj.SetValue("appid", jsApiConfig.AppId);             //公众账号ID
            inputObj.SetValue("mch_id", jsApiConfig.Partner);          //商户号
            inputObj.SetValue("spbill_create_ip", ToolHelper.GetIP()); //终端ip
            inputObj.SetValue("nonce_str", GenerateNonceStr());        //随机字符串

            //签名
            inputObj.SetValue("sign", inputObj.MakeSign());
            string xml = inputObj.ToXml();

            var start = DateTime.Now;

            string response = HttpService.Post(xml, url, false, timeOut);

            var end      = DateTime.Now;
            int timeCost = (int)((end - start).TotalMilliseconds);

            WxPayData result = new WxPayData();

            result.FromXml(response);

            ReportCostTime(url, timeCost, result);//测速上报

            return(result);
        }
 public JsApiPay()
 {
     jsApiConfig = new JsApiConfig();
 }