예제 #1
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="request"></param>
        /// <param name="config"></param>
        /// <param name="url"></param>
        /// <param name="isUseCert"></param>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public static async Task <T> ExecuteAsync <T>(IWechatRequest <T> request, WechatpayConfig config, string url, bool isUseCert = false, int timeout = 6)
        {
            var requestData = new WechatpayData();

            requestData.FromObject(request);
            var response = await ExecuteAsync(requestData, config, url, isUseCert, timeout);

            return(response.ToObject <T>());
        }
예제 #2
0
        /// <summary>
        /// 撤销订单API接口
        /// </summary>
        /// <param name="request">提交给撤销订单API接口的参数,out_trade_no和transaction_id必填一个</param>
        /// <param name="config"></param>
        /// <param name="timeOut">接口超时时间</param>
        /// <returns>成功时返回API调用结果,其他抛异常</returns>
        public static async Task <WechatpayData> ReverseAsyns(WechatpayData request, WechatpayConfig config, int timeOut = 6)
        {
            //检测必填参数
            if (!request.IsSet("out_trade_no") && !request.IsSet("transaction_id"))
            {
                throw new Exception("撤销订单API接口中,参数out_trade_no和transaction_id必须填写一个!");
            }

            return(await HttpService.ExecuteAsync(request, config, WechatConstants.ReverseOrderUrl, true, timeOut));
        }
예제 #3
0
        /// <summary>
        /// 根据当前系统时间加随机序列来生成订单号
        /// </summary>
        /// <param name="config"></param>
        /// <returns>订单号</returns>
        public static string GenerateOutTradeNo(WechatpayConfig config)
        {
            if (config == null || string.IsNullOrEmpty(config.AppId) || string.IsNullOrEmpty(config.MchId))
            {
                throw new Exception("收款账号不能为空");
            }
            var ran = new Random();

            return(string.Format("{0}{1}{2}", config.MchId, DateTime.Now.ToString("yyyyMMddHHmmss"), ran.Next(999)));
        }
예제 #4
0
        /// <summary>
        /// 支付成功回调
        /// </summary>
        /// <param name="request"></param>
        /// <param name="config"></param>
        /// <returns></returns>
        public static WechatNotifyResponse Notify(WechatpayData request, WechatpayConfig config)
        {
            if (config == null || string.IsNullOrEmpty(config.AppId))
            {
                throw new Exception("收款账号不能为空");
            }
            //验证签名,不通过会抛异常
            if (!request.CheckSign(config.SignType, config.SignKey))
            {
                throw new Exception("签名校验失败");
            }
            var result = request.ToObject <WechatNotifyResponse>();

            if (result.ReturnCode != WechatConstants.SUCCESS && result.ResultCode != WechatConstants.SUCCESS)
            {
                throw new Exception(result.ReturnMsg);
            }
            return(result);
        }
예제 #5
0
        /// <summary>
        /// 创建支付调起微信参数
        /// </summary>
        /// <param name="config"></param>
        /// <param name="prepay_id"></param>
        /// <param name="tradeType"></param>
        /// <param name="codeUrl"></param>
        /// <returns></returns>
        public static WechatpayData GetAppData(WechatpayConfig config, object prepay_id, string tradeType, string codeUrl)
        {
            if (config == null || string.IsNullOrEmpty(config.AppId) || string.IsNullOrEmpty(config.MchId))
            {
                throw new Exception("收款账号配置不能为空");
            }
            if (string.IsNullOrEmpty(config.SignKey))
            {
                throw new Exception("密钥配置不能为空");
            }
            var data = new WechatpayData();

            switch (tradeType)
            {
            case WechatConstants.APP:
                data.SetValue(WechatConstants.APPID.ToLower(), config.AppId);
                data.SetValue(WechatConstants.NONCESTR.ToLower(), HttpService.GenerateNonceStr());
                data.SetValue(WechatConstants.TIMESTAMP.ToLower(), (int)(DateTime.Now.ToUniversalTime().Ticks / 10000000 - 62135596800));
                data.SetValue(WechatConstants.PARTNERID, config.MchId);
                data.SetValue(WechatConstants.PREPAYID, prepay_id);
                data.SetValue(WechatConstants.PACKAGE.ToLower(), "Sign=WXPay");
                data.SetValue(WechatConstants.SIGN, data.MakeSign(config.SignType, config.SignKey));
                break;

            case WechatConstants.MWEB:
            case WechatConstants.JSAPI:
                data.SetValue(WechatConstants.APPID, config.AppId);
                data.SetValue(WechatConstants.NONCESTR, HttpService.GenerateNonceStr());
                data.SetValue(WechatConstants.TIMESTAMP, (int)(DateTime.Now.ToUniversalTime().Ticks / 10000000 - 62135596800));
                data.SetValue(WechatConstants.PACKAGE, "prepay_id=" + prepay_id);
                data.SetValue(WechatConstants.SIGNTYPE, config.SignType);
                data.SetValue(WechatConstants.PAYSIGN, data.MakeSign(config.SignType, config.SignKey));
                break;

            case WechatConstants.NATIVE:
                data.SetValue(WechatConstants.CODEURL, codeUrl);
                break;
            }
            return(data);
        }
예제 #6
0
        /// <summary>
        /// 申请退款
        /// </summary>
        /// <param name="request">提交给申请退款API的参数</param>
        /// <param name="config"></param>
        /// <param name="timeOut">超时时间</param>
        /// <returns>成功时返回接口调用结果,其他抛异常</returns>
        public static async Task <WechatpayData> RefundAsync(WechatpayData request, WechatpayConfig config, int timeOut = 6)
        {
            //检测必填参数
            if (!request.IsSet("out_trade_no") && !request.IsSet("transaction_id"))
            {
                throw new Exception("退款申请接口中,out_trade_no、transaction_id至少填一个!");
            }
            else if (!request.IsSet("out_refund_no"))
            {
                throw new Exception("退款申请接口中,缺少必填参数out_refund_no!");
            }
            else if (!request.IsSet("total_fee"))
            {
                throw new Exception("退款申请接口中,缺少必填参数total_fee!");
            }
            else if (!request.IsSet("refund_fee"))
            {
                throw new Exception("退款申请接口中,缺少必填参数refund_fee!");
            }

            return(await HttpService.ExecuteAsync(request, config, WechatConstants.RefundOrderUrl, true, timeOut));
        }
예제 #7
0
        /// <summary>
        /// 统一下单
        /// </summary>
        /// <param name="request">提交给统一下单API的参数</param>
        /// <param name="config"></param>
        /// <param name="timeOut">超时时间</param>
        /// <returns>成功时返回,其他抛异常</returns>
        public static async Task <WechatTradeAppPayResponse> CreateOrderAsync(WechatTradeAppPayRequest request, WechatpayConfig config, int timeOut = 6)
        {
            //检测必填参数
            if (string.IsNullOrEmpty(request.OutTradeNo))
            {
                throw new Exception("缺少统一支付接口必填参数out_trade_no!");
            }
            else if (string.IsNullOrEmpty(request.Body))
            {
                throw new Exception("缺少统一支付接口必填参数body!");
            }
            else if (request.TotalFee <= 0)
            {
                throw new Exception("缺少统一支付接口必填参数total_fee!");
            }
            else if (string.IsNullOrEmpty(request.TradeType))
            {
                throw new Exception("缺少统一支付接口必填参数trade_type!");
            }

            //关联参数
            if (request.TradeType == "JSAPI" && string.IsNullOrEmpty(request.OpenId))
            {
                throw new Exception("统一支付接口中,缺少必填参数openid!trade_type为JSAPI时,openid为必填参数!");
            }
            if (request.TradeType == "NATIVE" && string.IsNullOrEmpty(request.ProductId))
            {
                throw new Exception("统一支付接口中,缺少必填参数product_id!trade_type为JSAPI时,product_id为必填参数!");
            }

            //异步通知url未设置,则使用配置文件中的url
            if (string.IsNullOrEmpty(request.NotifyUrl))
            {
                throw new Exception("缺少统一支付接口必填参数notify_url");
            }

            var result = await HttpService.ExecuteAsync(request, config, WechatConstants.UnifiedOrderUrl);

            if (result.ReturnCode != WechatConstants.SUCCESS && result.ResultCode != WechatConstants.SUCCESS)
            {
                throw new Exception(result.ReturnMsg);
            }
            var data = HttpService.GetAppData(config, result.PrepayId, request.TradeType, result.CodeUrl);

            result.Body = data.ToXml();
            return(result);
        }
예제 #8
0
        /// <summary>
        /// 下载对账单
        /// </summary>
        /// <param name="request">提交给下载对账单API的参数</param>
        /// <param name="config"></param>
        /// <param name="timeOut">接口超时时间</param>
        /// <returns></returns>
        public static async Task <WechatpayData> DownloadBillAsync(WechatpayData request, WechatpayConfig config, int timeOut = 6)
        {
            //检测必填参数
            if (!request.IsSet("bill_date"))
            {
                throw new Exception("对账单接口中,缺少必填参数bill_date!");
            }

            return(await HttpService.ExecuteAsync(request, config, WechatConstants.DownloadBillUrl, false, timeOut));//调用HTTP通信接口以提交数据到API
        }
예제 #9
0
        /// <summary>
        /// 关闭订单
        /// </summary>
        /// <param name="request">提交给关闭订单API的参数</param>
        /// <param name="config"></param>
        /// <param name="timeOut">接口超时时间</param>
        /// <returns>成功时返回,其他抛异常</returns>
        public static async Task <WechatpayData> CloseOrderAsync(WechatpayData request, WechatpayConfig config, int timeOut = 6)
        {
            //检测必填参数
            if (!request.IsSet("out_trade_no"))
            {
                throw new Exception("关闭订单接口中,out_trade_no必填!");
            }

            return(await HttpService.ExecuteAsync(request, config, WechatConstants.CloseOrderUrl, false, timeOut));
        }
예제 #10
0
        /// <summary>
        /// 查询退款
        /// 提交退款申请后,通过该接口查询退款状态。退款有一定延时
        /// 用零钱支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态。
        /// </summary>
        /// <param name="request">out_refund_no、out_trade_no、transaction_id、refund_id四个参数必填一个</param>
        /// <param name="config"></param>
        /// <param name="timeOut">接口超时时间</param>
        /// <returns>成功时返回,其他抛异常</returns>
        public static async Task <WechatpayData> RefundQueryAsync(WechatpayData request, WechatpayConfig config, int timeOut = 6)
        {
            //检测必填参数
            if (!request.IsSet("out_refund_no") && !request.IsSet("out_trade_no") &&
                !request.IsSet("transaction_id") && !request.IsSet("refund_id"))
            {
                throw new Exception("退款查询接口中,out_refund_no、out_trade_no、transaction_id、refund_id四个参数必填一个!");
            }

            return(await HttpService.ExecuteAsync(request, config, WechatConstants.RefundOrderQueryUrl, false, timeOut));
        }
예제 #11
0
        /// <summary>
        /// 统一下单
        /// </summary>
        /// <param name="request">提交给统一下单API的参数</param>
        /// <param name="config"></param>
        /// <param name="timeOut">超时时间</param>
        /// <returns>成功时返回,其他抛异常</returns>
        public static async Task <WechatpayData> CreateOrderAsync(WechatpayData request, WechatpayConfig config, int timeOut = 6)
        {
            //检测必填参数
            if (!request.IsSet("out_trade_no"))
            {
                throw new Exception("缺少统一支付接口必填参数out_trade_no!");
            }
            else if (!request.IsSet("body"))
            {
                throw new Exception("缺少统一支付接口必填参数body!");
            }
            else if (!request.IsSet("total_fee"))
            {
                throw new Exception("缺少统一支付接口必填参数total_fee!");
            }
            else if (!request.IsSet("trade_type"))
            {
                throw new Exception("缺少统一支付接口必填参数trade_type!");
            }

            //关联参数
            if (request.GetValue("trade_type").ToString() == "JSAPI" && !request.IsSet("openid"))
            {
                throw new Exception("统一支付接口中,缺少必填参数openid!trade_type为JSAPI时,openid为必填参数!");
            }
            if (request.GetValue("trade_type").ToString() == "NATIVE" && !request.IsSet("product_id"))
            {
                throw new Exception("统一支付接口中,缺少必填参数product_id!trade_type为JSAPI时,product_id为必填参数!");
            }

            //异步通知url未设置,则使用配置文件中的url
            if (!request.IsSet("notify_url"))
            {
                throw new Exception("缺少统一支付接口必填参数notify_url");
            }

            var result = await HttpService.ExecuteAsync(request, config, WechatConstants.UnifiedOrderUrl, false, timeOut);

            var data = HttpService.GetAppData(config, result.GetValue("prepay_id"), request.GetValue("trade_type")?.ToString(), request.GetValue("code_url")?.ToString());

            result.SetValue("body", data.ToXml());
            return(result);
        }
예제 #12
0
        /// <summary>
        /// 下载对账单
        /// </summary>
        /// <param name="request">提交给下载对账单API的参数</param>
        /// <param name="config"></param>
        /// <param name="timeOut">接口超时时间</param>
        /// <returns></returns>
        public static async Task <WechatTradeDownloadResponse> DownloadBillAsync(WechatTradeDownloadRequest request, WechatpayConfig config, int timeOut = 6)
        {
            //检测必填参数
            if (string.IsNullOrEmpty(request.BillDate))
            {
                throw new Exception("对账单接口中,缺少必填参数bill_date!");
            }
            var requestData = new WechatpayData();

            requestData.FromObject(request);
            var response = await HttpService.ExecuteAsync(requestData, config, WechatConstants.DownloadBillUrl, false, timeOut);//调用HTTP通信接口以提交数据到API

            var result = response.ToObject <WechatTradeDownloadResponse>();

            if (result.ReturnCode != WechatConstants.SUCCESS && result.ResultCode != WechatConstants.SUCCESS)
            {
                throw new Exception(result.ReturnMsg);
            }
            result.Body = response.ToXml();
            return(result);
        }
예제 #13
0
        /// <summary>
        /// 关闭订单
        /// </summary>
        /// <param name="request">提交给关闭订单API的参数</param>
        /// <param name="config"></param>
        /// <param name="timeOut">接口超时时间</param>
        /// <returns>成功时返回,其他抛异常</returns>
        public static async Task <WechatTradeCloseResponse> CloseOrderAsync(WechatTradeCloseRequest request, WechatpayConfig config, int timeOut = 6)
        {
            //检测必填参数
            if (string.IsNullOrEmpty(request.OutTradeNo))
            {
                throw new Exception("关闭订单接口中,out_trade_no必填!");
            }

            var result = await HttpService.ExecuteAsync(request, config, WechatConstants.CloseOrderUrl);

            if (result.ReturnCode != WechatConstants.SUCCESS && result.ResultCode != WechatConstants.SUCCESS)
            {
                throw new Exception(result.ReturnMsg);
            }
            return(result);
        }
예제 #14
0
        /// <summary>
        /// 查询退款
        /// 提交退款申请后,通过该接口查询退款状态。退款有一定延时
        /// 用零钱支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态。
        /// </summary>
        /// <param name="request">out_refund_no、out_trade_no、transaction_id、refund_id四个参数必填一个</param>
        /// <param name="config"></param>
        /// <param name="timeOut">接口超时时间</param>
        /// <returns>成功时返回,其他抛异常</returns>
        public static async Task <WechatRefundQueryResponse> RefundQueryAsync(WechatRefundQueryRequest request, WechatpayConfig config, int timeOut = 6)
        {
            //检测必填参数
            if (string.IsNullOrEmpty(request.OutRefundNo) && string.IsNullOrEmpty(request.OutTradeNo) &&
                string.IsNullOrEmpty(request.RefundId) && string.IsNullOrEmpty(request.TransactionId))
            {
                throw new Exception("退款查询接口中,out_refund_no、out_trade_no、transaction_id、refund_id四个参数必填一个!");
            }

            var result = await HttpService.ExecuteAsync(request, config, WechatConstants.RefundOrderQueryUrl);

            if (result.ReturnCode != WechatConstants.SUCCESS && result.ResultCode != WechatConstants.SUCCESS)
            {
                throw new Exception(result.ReturnMsg);
            }
            return(result);
        }
예제 #15
0
        /// <summary>
        /// 申请退款
        /// </summary>
        /// <param name="request">提交给申请退款API的参数</param>
        /// <param name="config"></param>
        /// <param name="timeOut">超时时间</param>
        /// <returns>成功时返回接口调用结果,其他抛异常</returns>
        public static async Task <WechatRefundResponse> RefundAsync(WechatRefundRequest request, WechatpayConfig config, int timeOut = 6)
        {
            //检测必填参数
            if (string.IsNullOrEmpty(request.OutTradeNo) && string.IsNullOrEmpty(request.TransactionId))
            {
                throw new Exception("退款申请接口中,out_trade_no、transaction_id至少填一个!");
            }
            else if (string.IsNullOrEmpty(request.OutRefundNo))
            {
                throw new Exception("退款申请接口中,缺少必填参数out_refund_no!");
            }
            else if (request.TotalFee <= 0)
            {
                throw new Exception("退款申请接口中,缺少必填参数total_fee!");
            }
            else if (request.RefundFee <= 0)
            {
                throw new Exception("退款申请接口中,缺少必填参数refund_fee!");
            }

            var result = await HttpService.ExecuteAsync(request, config, WechatConstants.RefundOrderUrl, true);

            if (result.ReturnCode != WechatConstants.SUCCESS && result.ResultCode != WechatConstants.SUCCESS)
            {
                throw new Exception(result.ReturnMsg);
            }
            return(result);
        }
예제 #16
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="inputObj"></param>
        /// <param name="config"></param>
        /// <param name="url"></param>
        /// <param name="isUseCert"></param>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public static async Task <WechatpayData> ExecuteAsync(WechatpayData inputObj, WechatpayConfig config, string url, bool isUseCert = false, int timeout = 6)
        {
            if (config == null || string.IsNullOrEmpty(config.AppId) || string.IsNullOrEmpty(config.MchId))
            {
                throw new Exception("收款账号配置不能为空");
            }
            if (string.IsNullOrEmpty(config.SignKey))
            {
                throw new Exception("密钥配置不能为空");
            }
            inputObj.SetValue("appid", config.AppId);                                      //公众账号ID
            inputObj.SetValue("mch_id", config.MchId);                                     //商户号
            inputObj.SetValue("nonce_str", GenerateNonceStr());                            //随机字符串
            inputObj.SetValue("sign_type", config.SignType);                               //签名类型
            inputObj.SetValue("sign", inputObj.MakeSign(config.SignType, config.SignKey)); //签名

            string response = await PostAsync(inputObj.ToXml(), url, isUseCert, timeout, config.CertPath, config.CertPassword);

            var result = new WechatpayData();

            //若接口调用失败会返回xml格式的结果
            if (response.Substring(0, 5) == "<xml>")
            {
                result.FromXml(response);
                if (result.GetValue("return_code").ToString() != WechatConstants.SUCCESS)
                {
                    throw new Exception(result.GetValue("return_msg").ToString());
                }
                //验证签名,不通过会抛异常
                result.CheckSign(config.SignType, config.SignKey);
            }
            //接口调用成功则返回非xml格式的数据
            else
            {
                result.SetValue("return_code", "SUCCESS");
                result.SetValue("return_msg", "");
                result.SetValue("result_code", "SUCCESS");
                result.SetValue("body", response);
            }

            return(result);
        }