/// <summary>
        /// 事件之发送模板消息返回结果
        /// </summary>
        /// <param name="requestMessage"></param>
        /// <returns></returns>
        public override IResponseMessageBase OnEvent_TemplateSendJobFinishRequest(RequestMessageEvent_TemplateSendJobFinish requestMessage)
        {
            switch (requestMessage.Status)
            {
            case "success":
                //发送成功
                break;

            case "failed:user block":
                //送达由于用户拒收(用户设置拒绝接收公众号消息)而失败
                break;

            case "failed: system failed":
                //送达由于其他原因失败
                break;

            default:
                throw new WeixinException("未知模板消息状态:" + requestMessage.Status);
            }

            //注意:此方法内不能再发送模板消息,否则会造成无限循环!

            try
            {
                var msg = @"已向您发送模板消息状态:{0}MsgId:{1}".FormatWith(requestMessage.Status, requestMessage.MsgID);
                CustomApi.SendText(appId, WeixinOpenId, msg);//发送客服消息
            }
            catch (Exception e)
            {
                WeixinTrace.SendCustomLog("模板消息发送失败", e.ToString());
            }

            return(null);
        }
Example #2
0
        public ActionResult GetAccessToken()
        {
            //WeixinNullReferenceException 处理
            var myclass = new MyClass();

            try
            {
                if (myclass.Data == null)
                {
                    throw new WeixinNullReferenceException("MyClass Data Is Null", myclass);
                }
            }
            catch (WeixinNullReferenceException ex)
            {
                var obj = ex.ParentObject as MyClass;
                if (obj != null)
                {
                    obj.Data = "Data Is Null";
                }

                Senparc.Weixin.WeixinTrace.SendCustomLog("系统日志", "MyClass Data Is Null");
            }


            var accessToken = AccessTokenContainer.GetAccessToken(Config.AppId, true);

            //自定义 Log
            WeixinTrace.SendCustomLog("TestLog", "哈哈哈");

            return(Content("accessToken获取成功:" + accessToken.Substring(0, 20) + "\n" + Config.LogRecordCount.ToString()));
        }
Example #3
0
        public async Task <IActionResult> DecodeEncryptedData(string type, string sessionId, string encryptedData, string iv)
        {
            DecodeEntityBase decodedEntity = null;

            try
            {
                switch (type.ToUpper())
                {
                case "USERINFO":    //wx.getUserInfo()
                    decodedEntity = EncryptHelper.DecodeUserInfoBySessionId(
                        sessionId,
                        encryptedData, iv);
                    break;

                default:
                    break;
                }
            }
            catch (Exception ex)
            {
                WeixinTrace.SendCustomLog("EncryptHelper.DecodeUserInfoBySessionId 方法出错",
                                          $@"sessionId: {sessionId}
encryptedData: {encryptedData}
iv: {iv}
sessionKey: { (await SessionContainer.CheckRegisteredAsync(sessionId)
                ? (await SessionContainer.GetSessionAsync(sessionId)).SessionKey
                : "未保存sessionId")}

异常信息:
{ex.ToString()}
");
            }

            //检验水印
            var checkWatermark = false;

            if (decodedEntity != null)
            {
                checkWatermark = decodedEntity.CheckWatermark(WxOpenAppId);

                //保存用户信息(可选)
                if (checkWatermark && decodedEntity is DecodedUserInfo decodedUserInfo)
                {
                    var sessionBag = await SessionContainer.GetSessionAsync(sessionId);

                    if (sessionBag != null)
                    {
                        await SessionContainer.AddDecodedUserInfoAsync(sessionBag, decodedUserInfo);
                    }
                }
            }

            //注意:此处仅为演示,敏感信息请勿传递到客户端!
            return(Json(new
            {
                success = checkWatermark,
                //decodedEntity = decodedEntity,
                msg = $"水印验证:{(checkWatermark ? "通过" : "不通过")}"
            }));
        }
Example #4
0
        /// <summary>
        /// OAuthScope.snsapi_base方式回调
        /// </summary>
        /// <param name="code"></param>
        /// <param name="state"></param>
        /// <param name="returnUrl">用户最初尝试进入的页面</param>
        /// <returns></returns>
        public ActionResult BaseCallback(string code, string state, string returnUrl)
        {
            try
            {
                if (string.IsNullOrEmpty(code))
                {
                    return(Content("您拒绝了授权!"));
                }

                if (state != HttpContext.Session.GetString("State"))
                {
                    //这里的state其实是会暴露给客户端的,验证能力很弱,这里只是演示一下,
                    //建议用完之后就清空,将其一次性使用
                    //实际上可以存任何想传递的数据,比如用户ID,并且需要结合例如下面的Session["OAuthAccessToken"]进行验证
                    return(Content("验证失败!请从正规途径进入!"));
                }

                //通过,用code换取access_token
                var result = OAuthApi.GetAccessToken(appId, appSecret, code);
                if (result.errcode != ReturnCode.请求成功)
                {
                    return(Content("错误:" + result.errmsg));
                }

                //下面2个数据也可以自己封装成一个类,储存在数据库中(建议结合缓存)
                //如果可以确保安全,可以将access_token存入用户的cookie中,每一个人的access_token是不一样的
                HttpContext.Session.SetString("OAuthAccessTokenStartTime", SystemTime.Now.ToString());
                HttpContext.Session.SetString("OAuthAccessToken", result.ToJson());

                //因为这里还不确定用户是否关注本微信,所以只能试探性地获取一下
                OAuthUserInfo userInfo = null;
                try
                {
                    //已关注,可以得到详细信息
                    userInfo = OAuthApi.GetUserInfo(result.access_token, result.openid);

                    if (!string.IsNullOrEmpty(returnUrl))
                    {
                        return(Redirect(returnUrl));
                    }


                    ViewData["ByBase"] = true;
                    return(View("UserInfoCallback", userInfo));
                }
                catch (ErrorJsonResultException ex)
                {
                    Console.WriteLine(ex);
                    //未关注,只能授权,无法得到详细信息
                    //这里的 ex.JsonResult 可能为:"{\"errcode\":40003,\"errmsg\":\"invalid openid\"}"
                    return(Content("用户已授权,授权Token:" + result));
                }
            }
            catch (Exception ex)
            {
                WeixinTrace.SendCustomLog("BaseCallback 发生错误", ex.ToString());
                return(Content("发生错误:" + ex.ToString()));
            }
        }
Example #5
0
        public ActionResult GetAuthorizerInfoResultPage(string authorizerAppId)
        {
            WeixinTrace.SendCustomLog("查询授权信息json", authorizerAppId);//记录到日志中
            var getAuthorizerInfoResult = AuthorizerContainer.GetAuthorizerInfoResult(component_AppId, authorizerAppId);

            getAuthorizerInfoResult.authorization_info.authorizer_appid = authorizerAppId;
            return(Json(getAuthorizerInfoResult, JsonRequestBehavior.AllowGet));
        }
        public ActionResult Result(string openId, string template_id, int scene, string reserved)
        {
            //template_id就是微信后台可以看到的template_id

            if (reserved != Session["WeixinSubscribeMsgReserved"] as string)
            {
                //reserved用于保持请求和回调的状态,授权请后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验,开发者可以填写a-zA-Z0-9的参数值,最多128字节
                return(Content("请求错误!"));
            }

            WeixinTrace.SendCustomLog("一次性订阅消息-参数", string.Format("openId:{0},templateId:{1},scene:{2}", openId, template_id, scene));

            var action = Request.QueryString["action"];//MVC直接通过Action获取到的action参数为ActionName

            if (action == "confirm")
            {
                //发送提示
                var data = new
                {
                    content = new
                    {
                        value = "Value",
                        color = "#00ff00"
                    }
                };

                //var data1 = new
                //{
                //    content = new[]
                //    {
                //        new{
                //        value = "Value",
                //        color = "#00ff00"
                //        }
                //    }
                //};
                try
                {
                    TemplateApi.Subscribe(base.AppId, openId, template_id, scene, "这是一条“一次性订阅消息”", data);
                    return(Content("发送成功!"));
                }
                catch (ErrorJsonResultException e)
                {
                    if (e.JsonResult.errcode == ReturnCode.api功能未授权)
                    {
                        return(Content("功能正常,由于微信官方(程序或文档)问题,返回错误:" + e.JsonResult.errcode + "。请等待微信官方更新!"));
                    }
                    else
                    {
                        return(Content("发生错误:" + e.Message));
                    }
                }
            }
            else
            {
                return(Content("您已取消授权!"));
            }
        }
Example #7
0
        /// <summary>
        /// H5支付
        /// </summary>
        /// <param name="productId"></param>
        /// <param name="hc"></param>
        /// <returns></returns>
        public async Task <IActionResult> H5Pay(int productId, int hc)
        {
            try
            {
                //获取产品信息
                var products = ProductModel.GetFakeProductList();
                var product  = products.FirstOrDefault(z => z.Id == productId);
                if (product == null || product.GetHashCode() != hc)
                {
                    return(Content("商品信息不存在,或非法进入!1002"));
                }

                string openId = null;//此时在外部浏览器,无法或得到OpenId

                string sp_billno = Request.Query["order_no"];
                if (string.IsNullOrEmpty(sp_billno))
                {
                    //生成订单10位序列号,此处用时间和随机数生成,商户根据自己调整,保证唯一
                    sp_billno = string.Format("{0}{1}{2}", TenPayV3Info.MchId /*10位*/, SystemTime.Now.ToString("yyyyMMddHHmmss"),
                                              TenPayV3Util.BuildRandomStr(6));
                }
                else
                {
                    sp_billno = Request.Query["order_no"];
                }

                var timeStamp = TenPayV3Util.GetTimestamp();
                var nonceStr  = TenPayV3Util.GetNoncestr();

                var body  = product == null ? "test" : product.Name;
                var price = product == null ? 100 : (int)(product.Price * 100);

                var notifyUrl = TenPayV3Info.TenPayV3Notify.Replace("/TenpayV3/", "/TenpayRealV3/");

                TransactionsRequestData.Scene_Info sence_info = new(HttpContext.UserHostAddress()?.ToString(), null, null, new("Wap", null, null, null, null));

                TransactionsRequestData requestData = new(TenPayV3Info.AppId, TenPayV3Info.MchId, body, sp_billno, new TenpayDateTime(DateTime.Now.AddHours(1), false), null, notifyUrl, null, new() { currency = "CNY", total = price }, new(openId), null, null, sence_info);

                WeixinTrace.SendCustomLog("H5Pay接口请求", requestData.ToJson());

                var result = await _basePayApis.H5Async(requestData);

                WeixinTrace.SendCustomLog("H5Pay接口返回", result.ToJson());

                if (!result.VerifySignSuccess == true)
                {
                    return(Content("未通过验证,请检查数据有效性!"));
                }

                //直接跳转
                return(Redirect(result.h5_url));
            }
            catch (Exception ex)
            {
                WeixinTrace.WeixinExceptionLog(new WeixinException(ex.Message, ex));
                throw;
            }
        }
        /// <summary>
        /// 尝试下载
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public ActionResult Download(string guid)
        {
            var success = CheckCanDownload(guid);

            if (!success)
            {
                string message      = null;
                var    guidNotFound = !ConfigHelper.CodeCollection.ContainsKey(guid);
                if (guidNotFound)
                {
                    message = "审核失败,请从官方下载页面进入!";
                }
                else
                {
                    var codeRecord = ConfigHelper.CodeCollection[guid];
                    if (!codeRecord.AllowDownload)
                    {
                        message = string.Format("审核失败,文件不允许下载,或已经下载过!如需重新下载请刷新浏览器!(101 - {0})", guid);
                    }
                }

                message = message ?? string.Format("未通过审核,或此二维码已过期,请刷新网页后重新操作!(102 - {0})", guid);

                var file = File(Encoding.UTF8.GetBytes(message), "text/plain");
                file.FileDownloadName = "下载失败.txt";
                return(file);
            }
            else
            {
                var codeRecord = ConfigHelper.CodeCollection[guid];
                codeRecord.Used = true;
                //codeRecord.AllowDownload = false;//这里如果只允许一次下载,有的浏览器插件或者防护软件会自动访问页面上的链接,导致用户真实的下载时效
                var configHelper = new ConfigHelper();
                var filePath     = configHelper.Download(codeRecord.Version, codeRecord.IsWebVersion).Replace("/", "\\");
                //var file = File(filePath, "application/octet-stream");(此方法在.net core中会失败)

                //使用流的方式来发送
                var fs = new FileStream(filePath, FileMode.Open);
                var ms = new MemoryStream();
                fs.CopyTo(ms);
                ms.Seek(0, SeekOrigin.Begin);

                var file = File(ms, "application/octet-stream");

                var fileName = string.Format("Senparc.Weixin{0}-v{1}.{2}",
                                             codeRecord.IsWebVersion ? "-Web" : "",
                                             codeRecord.Version,
                                             filePath.Split('.').Last()//同步扩展名
                                             );

                file.FileDownloadName = fileName;

                WeixinTrace.SendCustomLog("download-path", filePath + " , " + file.FileDownloadName);

                return(file);
            }
        }
        public ActionResult GetPrepayid(string sessionId)
        {
            try
            {
                var sessionBag = SessionContainer.GetSession(sessionId);
                var openId = sessionBag.OpenId;


                //生成订单10位序列号,此处用时间和随机数生成,商户根据自己调整,保证唯一
                var sp_billno = string.Format("{0}{1}{2}", Config.SenparcWeixinSetting.TenPayV3_MchId /*10位*/, SystemTime.Now.ToString("yyyyMMddHHmmss"),
                        TenPayV3Util.BuildRandomStr(6));

                var timeStamp = TenPayV3Util.GetTimestamp();
                var nonceStr = TenPayV3Util.GetNoncestr();

                var body = "小程序微信支付Demo";
                var price = 1;//单位:分
                var xmlDataInfo = new TenPayV3UnifiedorderRequestData(WxOpenAppId, Config.SenparcWeixinSetting.TenPayV3_MchId, body, sp_billno,
                    price, Request.UserHostAddress, Config.SenparcWeixinSetting.TenPayV3_WxOpenTenpayNotify, TenPay.TenPayV3Type.JSAPI, openId, Config.SenparcWeixinSetting.TenPayV3_Key, nonceStr);

                var result = TenPayV3.Unifiedorder(xmlDataInfo);//调用统一订单接口

                WeixinTrace.SendCustomLog("统一订单接口调用结束", "请求:" + xmlDataInfo.ToJson() + "\r\n\r\n返回结果:" + result.ToJson());

                var packageStr = "prepay_id=" + result.prepay_id;

                //记录到缓存

                var cacheStrategy = CacheStrategyFactory.GetObjectCacheStrategyInstance();
                cacheStrategy.Set($"WxOpenUnifiedorderRequestData-{openId}", xmlDataInfo, TimeSpan.FromDays(4));//3天内可以发送模板消息
                cacheStrategy.Set($"WxOpenUnifiedorderResultData-{openId}", result, TimeSpan.FromDays(4));//3天内可以发送模板消息

                return Json(new
                {
                    success = true,
                    prepay_id = result.prepay_id,
                    appId = Config.SenparcWeixinSetting.WxOpenAppId,
                    timeStamp,
                    nonceStr,
                    package = packageStr,
                    //signType = "MD5",
                    paySign = TenPayV3.GetJsPaySign(WxOpenAppId, timeStamp, nonceStr, packageStr, Config.SenparcWeixinSetting.TenPayV3_Key)
                });
            }
            catch (Exception ex)
            {
                return Json(new
                {
                    success = false,
                    msg = ex.Message
                });
            }

        }
Example #10
0
 public void ConfigOnWeixinExceptionFunc(WeixinException ex)
 {
     try
     {
         string desc    = "发生错误" + ex.GetType().Name;
         string message = ex.Message;
         WeixinTrace.SendCustomLog(desc, desc);
     }
     catch (Exception e)
     {
         WeixinTrace.SendCustomLog("OnWeixinExceptionFunc过程错误", e.Message);
     }
 }
Example #11
0
        /// <summary>
        /// OAuthScope.snsapi_base方式回调
        /// </summary>
        /// <param name="code"></param>
        /// <param name="returnUrl">用户最初尝试进入的页面</param>
        /// <returns></returns>
        public ActionResult BaseCallback(string code, string returnUrl)
        {
            try
            {
                if (string.IsNullOrEmpty(code))
                {
                    return(Content("您拒绝了授权!"));
                }

                //通过,用code换取access_token
                var result = OAuthApi.GetAccessToken(appId, appSecret, code);
                if (result.errcode != ReturnCode.请求成功)
                {
                    return(Content("错误:" + result.errmsg));
                }

                //下面2个数据也可以自己封装成一个类,储存在数据库中(建议结合缓存)
                //如果可以确保安全,可以将access_token存入用户的cookie中,每一个人的access_token是不一样的
                HttpContext.Session.SetString("OAuthAccessTokenStartTime", SystemTime.Now.ToString());
                HttpContext.Session.SetString("OAuthAccessToken", result.ToJson());

                //因为这里还不确定用户是否关注本微信,所以只能试探性地获取一下
                OAuthUserInfo userInfo = null;
                try
                {
                    //已关注,可以得到详细信息
                    userInfo = OAuthApi.GetUserInfo(result.access_token, result.openid);

                    if (!string.IsNullOrEmpty(returnUrl))
                    {
                        return(Redirect(returnUrl));
                    }


                    ViewData["ByBase"] = true;
                    return(View("UserInfoCallback", userInfo));
                }
                catch (ErrorJsonResultException ex)
                {
                    //未关注,只能授权,无法得到详细信息
                    //这里的 ex.JsonResult 可能为:"{\"errcode\":40003,\"errmsg\":\"invalid openid\"}"
                    return(Content("用户已授权,授权Token:" + result, "text/html", Encoding.UTF8));
                }
            }
            catch (Exception ex)
            {
                WeixinTrace.SendCustomLog("BaseCallback 发生错误", ex.ToString());
                return(Content("发生错误:" + ex.ToString()));
            }
        }
Example #12
0
        /// <summary>
        /// 退款通知地址
        /// </summary>
        /// <returns></returns>
        public async Task <IActionResult> RefundNotifyUrl()
        {
            WeixinTrace.SendCustomLog("RefundNotifyUrl被访问", "IP" + HttpContext.UserHostAddress()?.ToString());

            NotifyReturnData returnData = new();

            try
            {
                var resHandler       = new TenPayNotifyHandler(HttpContext);
                var refundNotifyJson = await resHandler.AesGcmDecryptGetObjectAsync <RefundNotifyJson>();

                WeixinTrace.SendCustomLog("跟踪RefundNotifyUrl信息", refundNotifyJson.ToJson());

                string refund_status = refundNotifyJson.refund_status;
                if (/*refundNotifyJson.VerifySignSuccess == true &*/ refund_status == "SUCCESS")
                {
                    returnData.code    = "SUCCESS";
                    returnData.message = "OK";

                    //获取接口中需要用到的信息 例
                    string transaction_id = refundNotifyJson.transaction_id;
                    string out_trade_no   = refundNotifyJson.out_trade_no;
                    string refund_id      = refundNotifyJson.refund_id;
                    string out_refund_no  = refundNotifyJson.out_refund_no;
                    int    total_fee      = refundNotifyJson.amount.payer_total;
                    int    refund_fee     = refundNotifyJson.amount.refund;

                    //填写逻辑
                    WeixinTrace.SendCustomLog("RefundNotifyUrl被访问", "验证通过");
                }
                else
                {
                    returnData.code    = "FAILD";
                    returnData.message = "验证失败";
                    WeixinTrace.SendCustomLog("RefundNotifyUrl被访问", "验证失败");
                }

                //进行后续业务处理
            }
            catch (Exception ex)
            {
                returnData.code    = "FAILD";
                returnData.message = ex.Message;
                WeixinTrace.WeixinExceptionLog(new WeixinException(ex.Message, ex));
            }

            //https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay3_3.shtml
            return(Json(returnData));
        }
        public override IResponseMessageBase OnUnknownTypeRequest(RequestMessageUnknownType requestMessage)
        {
            /*
             * 此方法用于应急处理SDK没有提供的消息类型,
             * 原始XML可以通过requestMessage.RequestDocument(或this.RequestDocument)获取到。
             * 如果不重写此方法,遇到未知的请求类型将会抛出异常(v14.8.3 之前的版本就是这么做的)
             */
            var msgType         = Senparc.NeuChar.Helpers.MsgTypeHelper.GetRequestMsgTypeString(requestMessage.RequestDocument);
            var responseMessage = this.CreateResponseMessage <ResponseMessageText>();

            responseMessage.Content = "未知消息类型:" + msgType;

            WeixinTrace.SendCustomLog("未知请求消息类型", requestMessage.RequestDocument.ToString());//记录到日志中

            return(responseMessage);
        }
        public override async Task OnMessageReceiced(WebSocketHelper webSocketHandler, ReceivedMessage receivedMessage, string originalData)
        {
            if (receivedMessage == null || string.IsNullOrEmpty(receivedMessage.Message))
            {
                return;
            }

            var message = receivedMessage.Message;

            await webSocketHandler.SendMessage("originalData:" + originalData, webSocketHandler.WebSocket.Clients.Caller);

            await webSocketHandler.SendMessage("您发送了文字:" + message, webSocketHandler.WebSocket.Clients.Caller);

            await webSocketHandler.SendMessage("正在处理中(反转文字)...", webSocketHandler.WebSocket.Clients.Caller);

            await Task.Delay(1000);

            //处理文字
            var result = string.Concat(message.Reverse());
            await webSocketHandler.SendMessage(result, webSocketHandler.WebSocket.Clients.Caller);

            var appId = Config.SenparcWeixinSetting.WxOpenAppId;//与微信小程序账号后台的AppId设置保持一致,区分大小写。

            try
            {
                var sessionBag = SessionContainer.GetSession(receivedMessage.SessionId);

                //临时演示使用固定openId
                var openId = sessionBag != null ? sessionBag.OpenId : "onh7q0DGM1dctSDbdByIHvX4imxA";// "用户未正确登陆";

                //await webSocketHandler.SendMessage("OpenId:" + openId, webSocketHandler.WebSocket.Clients.Caller);
                //await webSocketHandler.SendMessage("FormId:" + formId);

                //群发
                await webSocketHandler.SendMessage($"[群发消息] [来自 OpenId:***{openId.Substring(openId.Length - 10, 10)},昵称:{sessionBag.DecodedUserInfo?.nickName}]:{message}", webSocketHandler.WebSocket.Clients.All);
            }
            catch (Exception ex)
            {
                var msg = ex.Message + "\r\n\r\n" + originalData + "\r\n\r\nAPPID:" + appId;

                await webSocketHandler.SendMessage(msg, webSocketHandler.WebSocket.Clients.Caller); //VS2017以下如果编译不通过,可以注释掉这一行

                WeixinTrace.SendCustomLog("WebSocket OnMessageReceiced()过程出错", msg);
            }
        }
Example #15
0
        public ActionResult Index()
        {
            var guid = Guid.NewGuid().ToString("n");

            ViewData["Guid"] = guid;

            var configHelper = new ConfigHelper();

            int qrCodeId = 0;
            CreateQrCodeResult qrResult = null;

            try
            {
                //chm二维码
                qrCodeId = configHelper.GetQrCodeId();
                qrResult = MP.AdvancedAPIs.QrCodeApi.Create(appId, 10000, qrCodeId, QrCode_ActionName.QR_SCENE);

                var qrCodeUrl = MP.AdvancedAPIs.QrCodeApi.GetShowQrCodeUrl(qrResult.ticket);
                ViewData["QrCodeUrl"] = qrCodeUrl;
            }
            catch (Exception e)
            {
                WeixinTrace.SendCustomLog("Document发生appsecret错误!", e.ToString());
                var accessTokenBags = AccessTokenContainer.GetAllItems();

                WeixinTrace.SendCustomLog("当前AccessToken信息", accessTokenBags.ToJson());
            }
            finally
            {
                ConfigHelper.CodeCollection[guid] = new CodeRecord()
                {
                    Key          = guid,
                    QrCodeId     = qrCodeId,
                    QrCodeTicket = qrResult
                };//添加对应关系

                //下载版本
                var config = configHelper.GetConfig();
                ViewData["Versions"]      = config.Versions;
                ViewData["WebVersions"]   = config.WebVersions;
                ViewData["DownloadCount"] = config.DownloadCount.ToString("##,###");
            }
            return(View());
        }
Example #16
0
        //DPBMARK_END


        #region 订单及退款

        /// <summary>
        /// 退款申请接口
        /// </summary>
        /// <returns></returns>
        public async Task <IActionResult> Refund()
        {
            try
            {
                WeixinTrace.SendCustomLog("进入退款流程", "1");

                string nonceStr = TenPayV3Util.GetNoncestr();

                string outTradeNo = HttpContext.Session.GetString("BillNo");
                if (!TradeNumberToTransactionId.TryGetValue(outTradeNo, out string transactionId))
                {
                    return(Content("transactionId 不正确,可能是服务器还没有收到微信回调确认通知,退款失败。请稍后刷新再试。"));
                }

                WeixinTrace.SendCustomLog("进入退款流程", "2 outTradeNo:" + outTradeNo + ",transactionId:" + transactionId);

                string outRefundNo = "OutRefunNo-" + SystemTime.Now.Ticks;
                int    totalFee    = int.Parse(HttpContext.Session.GetString("BillFee"));
                int    refundFee   = totalFee;
                string opUserId    = TenPayV3Info.MchId;
                var    notifyUrl   = "https://sdk.weixin.senparc.com/TenPayRealV3/RefundNotifyUrl";
                //var dataInfo = new TenPayV3RefundRequestData(TenPayV3Info.AppId, TenPayV3Info.MchId, TenPayV3Info.Key,
                //    null, nonceStr, null, outTradeNo, outRefundNo, totalFee, refundFee, opUserId, null, notifyUrl: notifyUrl);
                //TODO:该接口参数二选一传入
                var dataInfo = new RefundRequsetData(transactionId, null, outRefundNo, "Senparc TenPayV3 demo退款测试", notifyUrl, null, new RefundRequsetData.Amount(refundFee, null, refundFee, "CNY"), null);


                //#region 新方法(Senparc.Weixin v6.4.4+)
                //var result = TenPayOldV3.Refund(_serviceProvider, dataInfo);//证书地址、密码,在配置文件中设置,并在注册微信支付信息时自动记录
                //#endregion
                var result = await _basePayApis.RefundAsync(dataInfo);

                WeixinTrace.SendCustomLog("进入退款流程", "3 Result:" + result.ToJson());
                ViewData["Message"] = $"退款结果:{result.status} {result.ResultCode}。您可以刷新当前页面查看最新结果。";
                return(View());
                //return Json(result, JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                WeixinTrace.WeixinExceptionLog(new WeixinException(ex.Message, ex));

                throw;
            }
        }
Example #17
0
        /// <summary>
        /// 配置微信跟踪日志
        /// </summary>
        private void ConfigWeixinTraceLog()
        {
            //这里设为Debug状态时,/App_Data/WeixinTraceLog/目录下会生成日志文件记录所有的API请求日志,正式发布版本建议关闭
            Config.IsDebug = true;
            WeixinTrace.SendCustomLog("系统日志", "系统启动");//只在Senparc.Weixin.Config.IsDebug = true的情况下生效

            //自定义日志记录回调
            WeixinTrace.OnLogFunc = () =>
            {
                //加入每次触发Log后需要执行的代码
            };

            //当发生基于WeixinException的异常时触发
            WeixinTrace.OnWeixinExceptionFunc = ex =>
            {
                //加入每次触发WeixinExceptionLog后需要执行的代码
                var eventService = new EventService();
                eventService.ConfigOnWeixinExceptionFunc(ex);
            };
        }
Example #18
0
        public HttpResult Refund()
        {
            try
            {
                WeixinTrace.SendCustomLog("进入退款流程", "1");

                string nonceStr = TenPayV3Util.GetNoncestr();

                string outTradeNo = HttpContext.Session.GetString("BillNo");

                WeixinTrace.SendCustomLog("进入退款流程", "2 outTradeNo:" + outTradeNo);

                string outRefundNo = "OutRefunNo-" + SystemTime.Now.Ticks;
                int    totalFee    = int.Parse(HttpContext.Session.GetString("BillFee"));
                int    refundFee   = totalFee;
                string opUserId    = TenPayV3Info.MchId;
                var    notifyUrl   = "https://yufaquan.cn/wx/PayV3/RefundNotifyUrl";
                var    dataInfo    = new TenPayV3RefundRequestData(TenPayV3Info.AppId, TenPayV3Info.MchId, TenPayV3Info.Key,
                                                                   null, nonceStr, null, outTradeNo, outRefundNo, totalFee, refundFee, opUserId, null, notifyUrl: notifyUrl);

                #region 旧方法
                //var cert = @"D:\cert\apiclient_cert_SenparcRobot.p12";//根据自己的证书位置修改
                //var password = TenPayV3Info.MchId;//默认为商户号,建议修改
                //var result = TenPayV3.Refund(dataInfo, cert, password);
                #endregion

                #region 新方法(Senparc.Weixin v6.4.4+)
                var result = TenPayV3.Refund(_serviceProvider, dataInfo);//证书地址、密码,在配置文件中设置,并在注册微信支付信息时自动记录
                #endregion

                WeixinTrace.SendCustomLog("进入退款流程", "3 Result:" + result.ToJson());

                return(HttpResult.Success($"退款结果:{result.result_code} {result.err_code_des}。", null));
            }
            catch (Exception ex)
            {
                WeixinTrace.WeixinExceptionLog(new WeixinException(ex.Message, ex));

                throw;
            }
        }
Example #19
0
        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            var currentThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;

            if (!_start.ContainsKey(currentThreadId))
            {
                return;
            }

            try
            {
                //计算出当前页面访问耗时
                var costSeconds = (DateTime.Now - _start[currentThreadId]).TotalSeconds;
                if (costSeconds > 2)//如果耗时超过2秒,就是用log4net打印出,具体是哪个页面访问超过了2秒,具体使用了多长时间。
                {
                    LogUtility.TrackPageLoadPerformance.Warn($"页面执行时间超过{WARM_LOAD_SECONDS}秒。时间:{costSeconds},地址:{_url[currentThreadId]}");
                }

                if (!RecordActionName.IsNullOrEmpty() &&
                    (RecordActionName == "*" ||
                     RecordActionName.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries)
                     .Select(z => z.Trim().ToUpper()).Contains(filterContext.RouteData.DataTokens["action"]))
                    )
                {
                    var msg =
                        $"页面【{filterContext.RouteData.Values["Action"]}】执行时间:{costSeconds}秒,地址:{_url[currentThreadId]}";
                    LogUtility.TrackPageLoadPerformance.Debug(msg);
                    WeixinTrace.SendCustomLog("页面性能", msg);
                }
            }
            catch (Exception ex)
            {
                LogUtility.TrackPageLoadPerformance.ErrorFormat(ex.Message, ex);
            }
            finally
            {
                _start.Remove(currentThreadId);
                _url.Remove(currentThreadId);
            }
        }
        public async Task <IActionResult> DecodeEncryptedData(string type, string sessionId, string encryptedData, string iv)
        {
            DecodeEntityBase      decodedEntity = null;
            CoreCmsUserWeChatInfo userInfo      = null;

            try
            {
                switch (type.ToUpper())
                {
                case "USERINFO":    //wx.getUserInfo()
                    decodedEntity = EncryptHelper.DecodeUserInfoBySessionId(sessionId, encryptedData, iv);
                    break;

                default:
                    break;
                }
            }
            catch (Exception ex)
            {
                WeixinTrace.SendCustomLog("EncryptHelper.DecodeUserInfoBySessionId 方法出错",
                                          $@"sessionId: {sessionId}encryptedData: {encryptedData}iv: {iv}sessionKey: { (await SessionContainer.CheckRegisteredAsync(sessionId)
                ? (await SessionContainer.GetSessionAsync(sessionId)).SessionKey
                : "未保存sessionId")}异常信息:{ex.ToString()}");
            }

            //检验水印
            var checkWatermark = false;

            if (decodedEntity != null)
            {
                checkWatermark = decodedEntity.CheckWatermark(WxOpenAppId);

                //保存用户信息(可选)
                if (checkWatermark && decodedEntity is DecodedUserInfo decodedUserInfo)
                {
                    var sessionBag = await SessionContainer.GetSessionAsync(sessionId);

                    if (sessionBag != null)
                    {
                        await SessionContainer.AddDecodedUserInfoAsync(sessionBag, decodedUserInfo);
                    }
                    //更新数据库讯息
                    userInfo = _userWeChatInfoServices.QueryByClause(p => p.openid == decodedUserInfo.openId);
                    if (userInfo == null)
                    {
                        userInfo            = new CoreCmsUserWeChatInfo();
                        userInfo.type       = (int)GlobalEnumVars.UserAccountTypes.微信小程序;
                        userInfo.openid     = decodedUserInfo.openId;
                        userInfo.sessionKey = sessionBag.SessionKey;
                        userInfo.unionId    = decodedUserInfo.unionId;
                        userInfo.avatar     = decodedUserInfo.avatarUrl;
                        userInfo.nickName   = decodedUserInfo.nickName;
                        userInfo.gender     = decodedUserInfo.gender;
                        userInfo.language   = "";
                        userInfo.city       = decodedUserInfo.city;
                        userInfo.province   = decodedUserInfo.province;
                        userInfo.country    = decodedUserInfo.country;
                        userInfo.mobile     = "";
                        userInfo.createTime = DateTime.Now;
                        var id = _userWeChatInfoServices.Insert(userInfo);
                        if (id > 0)
                        {
                            userInfo.id = id;
                            _userWeChatInfoServices.Update(p => new CoreCmsUserWeChatInfo()
                            {
                                userId = id
                            }, p => p.id == id);
                        }
                    }
                    else
                    {
                        userInfo.gender   = decodedUserInfo.gender;
                        userInfo.city     = decodedUserInfo.city;
                        userInfo.avatar   = decodedUserInfo.avatarUrl;
                        userInfo.country  = decodedUserInfo.country;
                        userInfo.nickName = decodedUserInfo.nickName;
                        userInfo.province = decodedUserInfo.province;
                        userInfo.unionId  = decodedUserInfo.unionId;
                        userInfo.gender   = decodedUserInfo.gender;
                        _userWeChatInfoServices.Update(userInfo);
                    }
                }
            }

            //注意:此处仅为演示,敏感信息请勿传递到客户端!
            return(Json(new
            {
                success = checkWatermark,
                userInfo = userInfo,
                msg = string.Format("水印验证:{0}",
                                    checkWatermark ? "通过" : "不通过")
            }));
        }
Example #21
0
        public override async Task OnMessageReceiced(WebSocketHelper webSocketHandler, ReceivedMessage receivedMessage, string originalData)
        {
            if (receivedMessage == null || string.IsNullOrEmpty(receivedMessage.Message))
            {
                return;
            }

            var message = receivedMessage.Message;

            await webSocketHandler.SendMessage("originalData:" + originalData);

            await webSocketHandler.SendMessage("您发送了文字:" + message);

            await webSocketHandler.SendMessage("正在处理中...");

            await Task.Delay(1000);

            //处理文字
            var result = string.Concat(message.Reverse());
            await webSocketHandler.SendMessage(result);

#if NET45
            var appId = Config.SenparcWeixinSetting.WxOpenAppId; //与微信小程序账号后台的AppId设置保持一致,区分大小写。
#else
            var appId = "WxOpenAppId";                           //与微信小程序账号后台的AppId设置保持一致,区分大小写。
#endif


            try
            {
                //发送模板消息
                var formId = receivedMessage.FormId;//发送模板消息使用,需要在wxml中设置<form report-submit="true">

                var sessionBag = SessionContainer.GetSession(receivedMessage.SessionId);

                //临时演示使用固定openId
                var openId = sessionBag != null ? sessionBag.OpenId : "onh7q0DGM1dctSDbdByIHvX4imxA";// "用户未正确登陆";

                await webSocketHandler.SendMessage("OpenId:" + openId);

                //await webSocketHandler.SendMessage("FormId:" + formId);

                if (sessionBag == null)
                {
                    openId = "onh7q0DGM1dctSDbdByIHvX4imxA";//临时测试
                }

                //var data = new WxOpenTemplateMessage_PaySuccessNotice(
                //    "在线购买", SystemTime.Now, "图书众筹", "1234567890",
                //    100, "400-9939-858", "http://sdk.senparc.weixin.com");

                var data = new
                {
                    keyword1 = new TemplateDataItem("来自小程序WebSocket的模板消息"),
                    keyword2 = new TemplateDataItem(SystemTime.Now.LocalDateTime.ToString()),
                    keyword3 = new TemplateDataItem("Name"),
                    keyword4 = new TemplateDataItem("Number"),
                    keyword5 = new TemplateDataItem(100.ToString("C")),
                    keyword6 = new TemplateDataItem("400-031-8816"),
                };

                var tmResult = Senparc.Weixin.WxOpen.AdvancedAPIs.Template.TemplateApi.SendTemplateMessage(appId, openId, "Ap1S3tRvsB8BXsWkiILLz93nhe7S8IgAipZDfygy9Bg", data, receivedMessage.FormId, "pages/websocket/websocket", "websocket",
                                                                                                           null);
            }
            catch (Exception ex)
            {
                var msg = ex.Message + "\r\n\r\n" + originalData + "\r\n\r\nAPPID:" + appId;

                await webSocketHandler.SendMessage(msg); //VS2017以下如果编译不通过,可以注释掉这一行

                WeixinTrace.SendCustomLog("WebSocket OnMessageReceiced()过程出错", msg);
            }
        }
Example #22
0
 /// <summary>
 /// 小程序微信支付回调
 /// </summary>
 /// <returns></returns>
 public ActionResult PayNotifyUrlWxOpen()
 {
     WeixinTrace.SendCustomLog("小程序微信支付回调", "TenPayV3Controller.PayNotifyUrlWxOpen()");
     return(PayNotifyUrl(true));//调用正常的流程
 }
Example #23
0
        /// <summary>
        /// JS-SDK支付回调地址(在统一下单接口中设置notify_url)
        /// </summary>
        /// <returns></returns>
        public ActionResult PayNotifyUrl(bool isWxOpenPay = false)//注意:统一下单接口中不能带参数!
        {
            WeixinTrace.SendCustomLog("微信支付回调", "来源:" + (isWxOpenPay ? "微信支付" : "小程序支付"));

            try
            {
                ResponseHandler resHandler = new ResponseHandler(null);

                string return_code = resHandler.GetParameter("return_code");
                string return_msg  = resHandler.GetParameter("return_msg");

                bool paySuccess = false;

                resHandler.SetKey(TenPayV3Info.Key);
                //验证请求是否从微信发过来(安全)
                if (resHandler.IsTenpaySign() && return_code.ToUpper() == "SUCCESS")
                {
                    paySuccess = true;//正确的订单处理
                    //直到这里,才能认为交易真正成功了,可以进行数据库操作,但是别忘了返回规定格式的消息!
                }
                else
                {
                    paySuccess = false;//错误的订单处理
                }

                if (paySuccess)
                {
                    /* 这里可以进行订单处理的逻辑 */

                    //发送支付成功的模板消息
                    try
                    {
                        string appId  = Config.SenparcWeixinSetting.WeixinAppId;//与微信公众账号后台的AppId设置保持一致,区分大小写。
                        string openId = resHandler.GetParameter("openid");

                        if (isWxOpenPay)
                        {
                            //DPBMARK MiniProgram
                            var cacheStrategy           = CacheStrategyFactory.GetObjectCacheStrategyInstance();
                            var unifiedorderRequestData = cacheStrategy.Get <TenPayV3UnifiedorderRequestData>($"WxOpenUnifiedorderRequestData-{openId}"); //获取订单请求信息缓存
                            var unifedorderResult       = cacheStrategy.Get <UnifiedorderResult>($"WxOpenUnifiedorderResultData-{openId}");               //获取订单信息缓存

                            if (unifedorderResult != null || !string.IsNullOrEmpty(unifedorderResult.prepay_id))
                            {
                                Senparc.Weixin.WeixinTrace.SendCustomLog("支付成功模板消息参数(小程序)", appId + " , " + openId);

                                //小程序支付,发送小程序模板消息
                                var templateData = new WxOpenTemplateMessage_PaySuccessNotice(
                                    "在线购买(小程序支付)测试", SystemTime.Now, "小程序支付 | 注意:这条消息来自微信服务器异步回调,官方证明支付成功! | prepay_id:" + unifedorderResult.prepay_id,
                                    unifiedorderRequestData.OutTradeNo, unifiedorderRequestData.TotalFee, "400-031-8816", "https://weixin.senparc.com");

                                //微信官方已停用此接口
                                //Senparc.Weixin.WxOpen.AdvancedAPIs
                                //    .Template.TemplateApi
                                //    .SendTemplateMessage(
                                //        Config.SenparcWeixinSetting.WxOpenAppId, openId, templateData.TemplateId, templateData, unifedorderResult.prepay_id, "pages/index/index", "图书", "#fff00");
                            }
                            else
                            {
                                Senparc.Weixin.WeixinTrace.SendCustomLog("支付成功模板消息参数(小程序)", "prepayId未记录:" + appId + " , " + openId);
                            }
                            //DPBMARK_END
                        }
                        else
                        {
                            //微信公众号支付
                            var templateData = new WeixinTemplate_PaySuccess("https://weixin.senparc.com", "购买商品", "状态:" + return_code);

                            Senparc.Weixin.WeixinTrace.SendCustomLog("支付成功模板消息参数(公众号)", appId + " , " + openId);

                            var result = AdvancedAPIs.TemplateApi.SendTemplateMessage(appId, openId, templateData);
                        }
                    }
                    catch (Exception ex)
                    {
                        WeixinTrace.WeixinExceptionLog(new WeixinException("支付成功模板消息异常", ex));
                        //WeixinTrace.SendCustomLog("支付成功模板消息", ex.ToString());
                    }

                    WeixinTrace.SendCustomLog("PayNotifyUrl回调", "支付成功");
                }
                else
                {
                    Senparc.Weixin.WeixinTrace.SendCustomLog("PayNotifyUrl回调", "支付失败");
                }



                #region 记录日志

                var logDir = ServerUtility.ContentRootMapPath(string.Format("~/App_Data/TenPayNotify/{0}", SystemTime.Now.ToString("yyyyMMdd")));
                if (!Directory.Exists(logDir))
                {
                    Directory.CreateDirectory(logDir);
                }

                var logPath = Path.Combine(logDir, string.Format("{0}-{1}-{2}.txt", SystemTime.Now.ToString("yyyyMMdd"), SystemTime.Now.ToString("HHmmss"), Guid.NewGuid().ToString("n").Substring(0, 8)));

                using (var fileStream = System.IO.File.OpenWrite(logPath))
                {
                    var notifyXml = resHandler.ParseXML();
                    //fileStream.Write(Encoding.Default.GetBytes(res), 0, Encoding.Default.GetByteCount(res));

                    fileStream.Write(Encoding.Default.GetBytes(notifyXml), 0, Encoding.Default.GetByteCount(notifyXml));
                    fileStream.Close();
                }

                #endregion


                string xml = string.Format(@"<xml>
<return_code><![CDATA[{0}]]></return_code>
<return_msg><![CDATA[{1}]]></return_msg>
</xml>", return_code, return_msg);
                return(Content(xml, "text/xml"));
            }
            catch (Exception ex)
            {
                WeixinTrace.WeixinExceptionLog(new WeixinException(ex.Message, ex));
                throw;
            }
        }
Example #24
0
        public ActionResult Result(string openId, string template_id, string scene, string reserved)
        {
            //template_id就是微信后台可以看到的template_id

            if (reserved != Session["WeixinSubscribeMsgReserved"] as string)
            {
                //reserved用于保持请求和回调的状态,授权请后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验,开发者可以填写a-zA-Z0-9的参数值,最多128字节
                return(Content("请求错误!"));
            }

            WeixinTrace.SendCustomLog("一次性订阅消息-参数", string.Format("openId:{0},templateId:{1},scene:{2}", openId, template_id, scene));

            var action = Request.QueryString["action"];//MVC直接通过Action获取到的action参数为ActionName

            if (action == "confirm")
            {
                //发送提示
                var data = new
                {
                    content = new
                    {
                        value = @"您现在收到的是一条“一次订阅”消息。

感谢您对盛派网络的支持!

1、Senparc.Weixin SDK官方教程《微信开发深度解析》已经出版,请购买正版!

2、Senparc 官方视频教程《微信公众号+小程序快速开发》已经上线,点击【详情】观看或购买!",
                        color = "#008000"
                    }
                };

                //var data1 = new
                //{
                //    content = new[]
                //    {
                //        new{
                //        value = "Value",
                //        color = "#00ff00"
                //        },
                //         new{
                //        value = "Value2",
                //        color = "#ff0000"
                //        }
                //    }
                //};


                try
                {
                    var url = "https://book.weixin.senparc.com/book/videolinknetease?code=SenparcRobot-SubscribeMsg";
                    TemplateApi.Subscribe(base.AppId, openId, template_id, scene, "这是一条“一次性订阅消息”", data, url);
                    return(Content("发送成功!"));
                }
                catch (ErrorJsonResultException e)
                {
                    if (e.JsonResult.errcode == ReturnCode.api功能未授权)
                    {
                        return(Content("功能正常,由于微信官方(程序或文档)问题,返回错误:" + e.JsonResult.errcode + "。请等待微信官方更新!"));
                    }
                    else
                    {
                        return(Content("发生错误:" + e.Message));
                    }
                }
            }
            else
            {
                return(Content("您已取消授权!"));
            }
        }
        /// <summary>
        /// 点击事件
        /// </summary>
        /// <param name="requestMessage"></param>
        /// <returns></returns>
        public override IResponseMessageBase OnEvent_ClickRequest(RequestMessageEvent_Click requestMessage)
        {
            IResponseMessageBase reponseMessage = null;

            //菜单点击,需要跟创建菜单时的Key匹配

            switch (requestMessage.EventKey)
            {
            case "OneClick":
            {
                //这个过程实际已经在OnTextOrEventRequest中完成,这里不会执行到。
                var strongResponseMessage = CreateResponseMessage <ResponseMessageText>();
                reponseMessage = strongResponseMessage;
                strongResponseMessage.Content = "您点击了底部按钮。\r\n为了测试微信软件换行bug的应对措施,这里做了一个——\r\n换行";
            }
            break;

            case "SubClickRoot_Text":
            {
                var strongResponseMessage = CreateResponseMessage <ResponseMessageText>();
                reponseMessage = strongResponseMessage;
                strongResponseMessage.Content = "您点击了子菜单按钮。";
            }
            break;

            case "SubClickRoot_News":
            {
                var strongResponseMessage = CreateResponseMessage <ResponseMessageNews>();
                reponseMessage = strongResponseMessage;
                strongResponseMessage.Articles.Add(new Article()
                    {
                        Title       = "您点击了子菜单图文按钮",
                        Description = "您点击了子菜单图文按钮,这是一条图文信息。这个区域是Description内容\r\n可以使用\\r\\n进行换行。",
                        PicUrl      = "http://sdk.weixin.senparc.com/Images/qrcode.jpg",
                        Url         = "http://sdk.weixin.senparc.com"
                    });

                //随机添加一条图文,或只输出一条图文信息
                if (DateTime.Now.Second % 2 == 0)
                {
                    strongResponseMessage.Articles.Add(new Article()
                        {
                            Title       = "这是随机产生的第二条图文信息,用于测试多条图文的样式",
                            Description = "这是随机产生的第二条图文信息,用于测试多条图文的样式",
                            PicUrl      = "http://sdk.weixin.senparc.com/Images/qrcode.jpg",
                            Url         = "http://sdk.weixin.senparc.com"
                        });
                }
            }
            break;

            case "SubClickRoot_Music":
            {
                //上传缩略图
                var accessToken  = Containers.AccessTokenContainer.TryGetAccessToken(appId, appSecret);
                var uploadResult = AdvancedAPIs.MediaApi.UploadTemporaryMedia(accessToken, UploadMediaFileType.thumb,
                                                                              Server.GetMapPath("~/Images/Logo.thumb.jpg"));
                //PS:缩略图官方没有特别提示文件大小限制,实际测试哪怕114K也会返回文件过大的错误,因此尽量控制在小一点(当前图片39K)

                //设置音乐信息
                var strongResponseMessage = CreateResponseMessage <ResponseMessageMusic>();
                reponseMessage = strongResponseMessage;
                strongResponseMessage.Music.Title        = "天籁之音";
                strongResponseMessage.Music.Description  = "真的是天籁之音";
                strongResponseMessage.Music.MusicUrl     = "https://sdk.weixin.senparc.com/Content/music1.mp3";
                strongResponseMessage.Music.HQMusicUrl   = "https://sdk.weixin.senparc.com/Content/music1.mp3";
                strongResponseMessage.Music.ThumbMediaId = uploadResult.thumb_media_id;
            }
            break;

            case "SubClickRoot_Image":
            {
                //上传图片
                var accessToken  = Containers.AccessTokenContainer.TryGetAccessToken(appId, appSecret);
                var uploadResult = AdvancedAPIs.MediaApi.UploadTemporaryMedia(accessToken, UploadMediaFileType.image,
                                                                              Server.GetMapPath("~/Images/Logo.jpg"));
                //设置图片信息
                var strongResponseMessage = CreateResponseMessage <ResponseMessageImage>();
                reponseMessage = strongResponseMessage;
                strongResponseMessage.Image.MediaId = uploadResult.media_id;
            }
            break;

            case "SubClickRoot_Agent":    //代理消息
            {
                //获取返回的XML
                DateTime dt1 = DateTime.Now;
                reponseMessage = MessageAgent.RequestResponseMessage(this, agentUrl, agentToken, RequestDocument.ToString());
                //上面的方法也可以使用扩展方法:this.RequestResponseMessage(this,agentUrl, agentToken, RequestDocument.ToString());

                DateTime dt2 = DateTime.Now;

                if (reponseMessage is ResponseMessageNews)
                {
                    (reponseMessage as ResponseMessageNews)
                    .Articles[0]
                    .Description += string.Format("\r\n\r\n代理过程总耗时:{0}毫秒", (dt2 - dt1).Milliseconds);
                }
            }
            break;

            case "Member":    //托管代理会员信息
            {
                //原始方法为:MessageAgent.RequestXml(this,agentUrl, agentToken, RequestDocument.ToString());//获取返回的XML
                reponseMessage = this.RequestResponseMessage(agentUrl, agentToken, RequestDocument.ToString());
            }
            break;

            case "OAuth":    //OAuth授权测试
            {
                var strongResponseMessage = CreateResponseMessage <ResponseMessageNews>();

                strongResponseMessage.Articles.Add(new Article()
                    {
                        Title       = "OAuth2.0测试",
                        Description = "选择下面两种不同的方式进行测试,区别在于授权成功后,最后停留的页面。",
                        //Url = "http://sdk.weixin.senparc.com/oauth2",
                        //PicUrl = "http://sdk.weixin.senparc.com/Images/qrcode.jpg"
                    });

                strongResponseMessage.Articles.Add(new Article()
                    {
                        Title       = "OAuth2.0测试(不带returnUrl),测试环境可使用",
                        Description = "OAuth2.0测试(不带returnUrl)",
                        Url         = "http://sdk.weixin.senparc.com/oauth2",
                        PicUrl      = "http://sdk.weixin.senparc.com/Images/qrcode.jpg"
                    });

                var returnUrl = "/OAuth2/TestReturnUrl";
                strongResponseMessage.Articles.Add(new Article()
                    {
                        Title       = "OAuth2.0测试(带returnUrl),生产环境强烈推荐使用",
                        Description = "OAuth2.0测试(带returnUrl)",
                        Url         = "http://sdk.weixin.senparc.com/oauth2?returnUrl=" + returnUrl.UrlEncode(),
                        PicUrl      = "http://sdk.weixin.senparc.com/Images/qrcode.jpg"
                    });

                reponseMessage = strongResponseMessage;
            }
            break;

            case "Description":
            {
                var strongResponseMessage = CreateResponseMessage <ResponseMessageText>();
                strongResponseMessage.Content = GetWelcomeInfo();
                reponseMessage = strongResponseMessage;
            }
            break;

            case "SubClickRoot_PicPhotoOrAlbum":
            {
                var strongResponseMessage = CreateResponseMessage <ResponseMessageText>();
                reponseMessage = strongResponseMessage;
                strongResponseMessage.Content = "您点击了【微信拍照】按钮。系统将会弹出拍照或者相册发图。";
            }
            break;

            case "SubClickRoot_ScancodePush":
            {
                var strongResponseMessage = CreateResponseMessage <ResponseMessageText>();
                reponseMessage = strongResponseMessage;
                strongResponseMessage.Content = "您点击了【微信扫码】按钮。";
            }
            break;

            case "ConditionalMenu_Male":
            {
                var strongResponseMessage = CreateResponseMessage <ResponseMessageText>();
                reponseMessage = strongResponseMessage;
                strongResponseMessage.Content = "您点击了个性化菜单按钮,您的微信性别设置为:男。";
            }
            break;

            case "ConditionalMenu_Femle":
            {
                var strongResponseMessage = CreateResponseMessage <ResponseMessageText>();
                reponseMessage = strongResponseMessage;
                strongResponseMessage.Content = "您点击了个性化菜单按钮,您的微信性别设置为:女。";
            }
            break;

            case "GetNewMediaId":    //获取新的MediaId
            {
                var strongResponseMessage = CreateResponseMessage <ResponseMessageText>();
                try
                {
                    var result = AdvancedAPIs.MediaApi.UploadForeverMedia(appId, Server.GetMapPath("~/Images/logo.jpg"));
                    strongResponseMessage.Content = result.media_id;
                }
                catch (Exception e)
                {
                    strongResponseMessage.Content = "发生错误:" + e.Message;
                    WeixinTrace.SendCustomLog("调用UploadForeverMedia()接口发生异常", e.Message);
                }
            }
            break;

            default:
            {
                var strongResponseMessage = CreateResponseMessage <ResponseMessageText>();
                strongResponseMessage.Content = "您点击了按钮,EventKey:" + requestMessage.EventKey;
                reponseMessage = strongResponseMessage;
            }
            break;
            }

            return(reponseMessage);
        }
Example #26
0
        /// <summary>
        /// 退款申请接口
        /// </summary>
        /// <returns></returns>
        public ActionResult Refund()
        {
            try
            {
                WeixinTrace.SendCustomLog("进入退款流程", "1");

                string nonceStr = TenPayV3Util.GetNoncestr();

                string outTradeNo = HttpContext.Session.GetString("BillNo");

                WeixinTrace.SendCustomLog("进入退款流程", "2 outTradeNo:" + outTradeNo);

                string outRefundNo = "OutRefunNo-" + SystemTime.Now.Ticks;
                int    totalFee    = int.Parse(HttpContext.Session.GetString("BillFee"));
                int    refundFee   = totalFee;
                string opUserId    = TenPayV3Info.MchId;
                var    notifyUrl   = "https://sdk.weixin.senparc.com/TenPayV3/RefundNotifyUrl";
                var    dataInfo    = new TenPayV3RefundRequestData(TenPayV3Info.AppId, TenPayV3Info.MchId, TenPayV3Info.Key,
                                                                   null, nonceStr, null, outTradeNo, outRefundNo, totalFee, refundFee, opUserId, null, notifyUrl: notifyUrl);

                #region 旧方法
                //var cert = @"D:\cert\apiclient_cert_SenparcRobot.p12";//根据自己的证书位置修改
                //var password = TenPayV3Info.MchId;//默认为商户号,建议修改
                //var result = TenPayOldV3.Refund(dataInfo, cert, password);
                #endregion

                #region 新方法(Senparc.Weixin v6.4.4+)
                var result = TenPayOldV3.Refund(_serviceProvider, dataInfo);//证书地址、密码,在配置文件中设置,并在注册微信支付信息时自动记录
                #endregion

                WeixinTrace.SendCustomLog("进入退款流程", "3 Result:" + result.ToJson());
                ViewData["Message"] = $"退款结果:{result.result_code} {result.err_code_des}。您可以刷新当前页面查看最新结果。";
                return(View());
                //return Json(result, JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                WeixinTrace.WeixinExceptionLog(new WeixinException(ex.Message, ex));

                throw;
            }

            #region 原始方法

            //RequestHandler packageReqHandler = new RequestHandler(null);

            //设置package订单参数
            //packageReqHandler.SetParameter("appid", TenPayV3Info.AppId);		 //公众账号ID
            //packageReqHandler.SetParameter("mch_id", TenPayV3Info.MchId);	     //商户号
            //packageReqHandler.SetParameter("out_trade_no", "124138540220170502163706139412"); //填入商家订单号
            ////packageReqHandler.SetParameter("out_refund_no", "");                //填入退款订单号
            //packageReqHandler.SetParameter("total_fee", "");                    //填入总金额
            //packageReqHandler.SetParameter("refund_fee", "100");                //填入退款金额
            //packageReqHandler.SetParameter("op_user_id", TenPayV3Info.MchId);   //操作员Id,默认就是商户号
            //packageReqHandler.SetParameter("nonce_str", nonceStr);              //随机字符串
            //string sign = packageReqHandler.CreateMd5Sign("key", TenPayV3Info.Key);
            //packageReqHandler.SetParameter("sign", sign);	                    //签名
            ////退款需要post的数据
            //string data = packageReqHandler.ParseXML();

            ////退款接口地址
            //string url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
            ////本地或者服务器的证书位置(证书在微信支付申请成功发来的通知邮件中)
            //string cert = @"D:\cert\apiclient_cert_SenparcRobot.p12";
            ////私钥(在安装证书时设置)
            //string password = TenPayV3Info.MchId;
            //ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
            ////调用证书
            //X509Certificate2 cer = new X509Certificate2(cert, password, X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet);

            //#region 发起post请求
            //HttpWebRequest webrequest = (HttpWebRequest)HttpWebRequest.Create(url);
            //webrequest.ClientCertificates.Add(cer);
            //webrequest.Method = "post";

            //byte[] postdatabyte = Encoding.UTF8.GetBytes(data);
            //webrequest.ContentLength = postdatabyte.Length;
            //Stream stream;
            //stream = webrequest.GetRequestStream();
            //stream.Write(postdatabyte, 0, postdatabyte.Length);
            //stream.Close();

            //HttpWebResponse httpWebResponse = (HttpWebResponse)webrequest.GetResponse();
            //StreamReader streamReader = new StreamReader(httpWebResponse.GetResponseStream());
            //string responseContent = streamReader.ReadToEnd();
            //#endregion

            //// var res = XDocument.Parse(responseContent);
            ////string openid = res.Element("xml").Element("out_refund_no").Value;
            //return Content("申请成功:<br>" + HttpUtility.RequestUtility.HtmlEncode(responseContent));

            #endregion
        }
Example #27
0
        /// <summary>
        /// 退款通知地址
        /// </summary>
        /// <returns></returns>
        public ActionResult RefundNotifyUrl()
        {
            WeixinTrace.SendCustomLog("RefundNotifyUrl被访问", "IP" + HttpContext.UserHostAddress()?.ToString());

            string responseCode = "FAIL";
            string responseMsg  = "FAIL";

            try
            {
                ResponseHandler resHandler = new ResponseHandler(HttpContext);

                string return_code = resHandler.GetParameter("return_code");
                string return_msg  = resHandler.GetParameter("return_msg");

                WeixinTrace.SendCustomLog("跟踪RefundNotifyUrl信息", resHandler.ParseXML());

                if (return_code == "SUCCESS")
                {
                    responseCode = "SUCCESS";
                    responseMsg  = "OK";

                    string appId     = resHandler.GetParameter("appid");
                    string mch_id    = resHandler.GetParameter("mch_id");
                    string nonce_str = resHandler.GetParameter("nonce_str");
                    string req_info  = resHandler.GetParameter("req_info");

                    if (!appId.Equals(Senparc.Weixin.Config.SenparcWeixinSetting.TenPayV3_AppId))
                    {
                        /*
                         * 注意:
                         * 这里添加过滤只是因为盛派Demo经常有其他公众号错误地设置了我们的地址,
                         * 导致无法正常解密,平常使用不需要过滤!
                         */
                        SenparcTrace.SendCustomLog("RefundNotifyUrl 的 AppId 不正确",
                                                   $"appId:{appId}\r\nmch_id:{mch_id}\r\nreq_info:{req_info}");
                        return(Content("faild"));
                    }

                    SenparcTrace.SendCustomLog("解密 - req_info", req_info);

                    var decodeReqInfo = TenPayV3Util.DecodeRefundReqInfo(req_info, TenPayV3Info.Key);

                    SenparcTrace.SendCustomLog("解密 - decodeReqInfo", decodeReqInfo);

                    var decodeDoc = XDocument.Parse(decodeReqInfo);

                    //获取接口中需要用到的信息
                    string transaction_id       = decodeDoc.Root.Element("transaction_id").Value;
                    string out_trade_no         = decodeDoc.Root.Element("out_trade_no").Value;
                    string refund_id            = decodeDoc.Root.Element("refund_id").Value;
                    string out_refund_no        = decodeDoc.Root.Element("out_refund_no").Value;
                    int    total_fee            = int.Parse(decodeDoc.Root.Element("total_fee").Value);
                    int?   settlement_total_fee = decodeDoc.Root.Element("settlement_total_fee") != null
                            ? int.Parse(decodeDoc.Root.Element("settlement_total_fee").Value)
                            : null as int?;

                    int    refund_fee = int.Parse(decodeDoc.Root.Element("refund_fee").Value);
                    int    tosettlement_refund_feetal_fee = int.Parse(decodeDoc.Root.Element("settlement_refund_fee").Value);
                    string refund_status         = decodeDoc.Root.Element("refund_status").Value;
                    string success_time          = decodeDoc.Root.Element("success_time").Value;
                    string refund_recv_accout    = decodeDoc.Root.Element("refund_recv_accout").Value;
                    string refund_account        = decodeDoc.Root.Element("refund_account").Value;
                    string refund_request_source = decodeDoc.Root.Element("refund_request_source").Value;


                    WeixinTrace.SendCustomLog("RefundNotifyUrl被访问", "验证通过");

                    //进行后续业务处理
                }
            }
            catch (Exception ex)
            {
                responseMsg = ex.Message;
                WeixinTrace.WeixinExceptionLog(new WeixinException(ex.Message, ex));
            }

            string xml = string.Format(@"<xml>
<return_code><![CDATA[{0}]]></return_code>
<return_msg><![CDATA[{1}]]></return_msg>
</xml>", responseCode, responseMsg);

            return(Content(xml, "text/xml"));
        }
        /// <summary>
        /// 【异步方法】执行微信请求
        /// </summary>
        public override async Task BuildResponseMessageAsync()
        {
            #region NeuChar 执行过程

            var weixinAppId = this._postModel == null ? "" : this._postModel.AppId;

            switch (RequestMessage.MsgType)
            {
            case RequestMsgType.Text:
            {
                try
                {
                    var requestMessage = RequestMessage as RequestMessageText;
                    ResponseMessage = await CurrentMessageHandlerNode.ExecuteAsync(requestMessage, this, weixinAppId)
                                      ?? ((await(OnTextOrEventRequestAsync(requestMessage))
                                           ?? (await OnTextRequestAsync(requestMessage))));
                }
                catch (Exception ex)
                {
                    SenparcTrace.SendCustomLog("mp-response error", ex.Message + "\r\n|||\r\n" + (ex.InnerException != null ? ex.InnerException.ToString() : ""));
                }
            }
            break;

            case RequestMsgType.Location:
                ResponseMessage = await OnLocationRequestAsync(RequestMessage as RequestMessageLocation);

                break;

            case RequestMsgType.Image:

                WeixinTrace.SendCustomLog("NeuChar Image", $"appid:{weixinAppId}");

                ResponseMessage = await CurrentMessageHandlerNode.ExecuteAsync(RequestMessage, this, weixinAppId) ?? await OnImageRequestAsync(RequestMessage as RequestMessageImage);

                break;

            case RequestMsgType.Voice:
                ResponseMessage = await OnVoiceRequestAsync(RequestMessage as RequestMessageVoice);

                break;

            case RequestMsgType.Video:
                ResponseMessage = await OnVideoRequestAsync(RequestMessage as RequestMessageVideo);

                break;

            case RequestMsgType.Link:
                ResponseMessage = await OnLinkRequestAsync(RequestMessage as RequestMessageLink);

                break;

            case RequestMsgType.ShortVideo:
                ResponseMessage = await OnShortVideoRequestAsync(RequestMessage as RequestMessageShortVideo);

                break;

            case RequestMsgType.File:
                ResponseMessage = await OnFileRequestAsync(RequestMessage as RequestMessageFile);

                break;

            case RequestMsgType.NeuChar:
                ResponseMessage = await OnNeuCharRequestAsync(RequestMessage as RequestMessageNeuChar);

                break;

            case RequestMsgType.Unknown:
                ResponseMessage = await OnUnknownTypeRequestAsync(RequestMessage as RequestMessageUnknownType);

                break;

            case RequestMsgType.Event:
            {
                var requestMessageText = (RequestMessage as IRequestMessageEventBase).ConvertToRequestMessageText();
                ResponseMessage = await CurrentMessageHandlerNode.ExecuteAsync(RequestMessage, this, weixinAppId) ??
                                  await OnTextOrEventRequestAsync(requestMessageText) ??
                                  (await OnEventRequestAsync(RequestMessage as IRequestMessageEventBase));
            }
            break;

            default:
                Weixin.WeixinTrace.SendCustomLog("NeuChar", "未知的MsgType请求类型" + RequestMessage.MsgType);
                //throw new UnknownRequestMsgTypeException("未知的MsgType请求类型", null);
                break;
            }

            #endregion
        }
Example #29
0
        /// <summary>
        /// 退款通知地址
        /// </summary>
        /// <returns></returns>
        public ActionResult RefundNotifyUrl()
        {
            WeixinTrace.SendCustomLog("RefundNotifyUrl被访问", "IP" + HttpContext.UserHostAddress()?.ToString());

            string responseCode = "FAIL";
            string responseMsg  = "FAIL";

            try
            {
                ResponseHandler resHandler = new ResponseHandler(null);

                string return_code = resHandler.GetParameter("return_code");
                string return_msg  = resHandler.GetParameter("return_msg");

                WeixinTrace.SendCustomLog("跟踪RefundNotifyUrl信息", resHandler.ParseXML());

                if (return_code == "SUCCESS")
                {
                    responseCode = "SUCCESS";
                    responseMsg  = "OK";

                    string appId     = resHandler.GetParameter("appid");
                    string mch_id    = resHandler.GetParameter("mch_id");
                    string nonce_str = resHandler.GetParameter("nonce_str");
                    string req_info  = resHandler.GetParameter("req_info");

                    var decodeReqInfo = TenPayV3Util.DecodeRefundReqInfo(req_info, TenPayV3Info.Key);
                    var decodeDoc     = XDocument.Parse(decodeReqInfo);

                    //获取接口中需要用到的信息
                    string transaction_id       = decodeDoc.Root.Element("transaction_id").Value;
                    string out_trade_no         = decodeDoc.Root.Element("out_trade_no").Value;
                    string refund_id            = decodeDoc.Root.Element("refund_id").Value;
                    string out_refund_no        = decodeDoc.Root.Element("out_refund_no").Value;
                    int    total_fee            = int.Parse(decodeDoc.Root.Element("total_fee").Value);
                    int?   settlement_total_fee = decodeDoc.Root.Element("settlement_total_fee") != null
                            ? int.Parse(decodeDoc.Root.Element("settlement_total_fee").Value)
                            : null as int?;

                    int    refund_fee = int.Parse(decodeDoc.Root.Element("refund_fee").Value);
                    int    tosettlement_refund_feetal_fee = int.Parse(decodeDoc.Root.Element("settlement_refund_fee").Value);
                    string refund_status         = decodeDoc.Root.Element("refund_status").Value;
                    string success_time          = decodeDoc.Root.Element("success_time").Value;
                    string refund_recv_accout    = decodeDoc.Root.Element("refund_recv_accout").Value;
                    string refund_account        = decodeDoc.Root.Element("refund_account").Value;
                    string refund_request_source = decodeDoc.Root.Element("refund_request_source").Value;

                    //进行业务处理
                }
            }
            catch (Exception ex)
            {
                responseMsg = ex.Message;
                WeixinTrace.WeixinExceptionLog(new WeixinException(ex.Message, ex));
            }

            string xml = string.Format(@"<xml>
<return_code><![CDATA[{0}]]></return_code>
<return_msg><![CDATA[{1}]]></return_msg>
</xml>", responseCode, responseMsg);

            return(Content(xml, "text/xml"));
        }
Example #30
0
        /// <summary>
        /// 【异步方法】执行微信请求
        /// </summary>
        public override async Task ExecuteAsync()
        {
            if (CancelExcute)
            {
                return;
            }

            await OnExecutingAsync();

            if (CancelExcute)
            {
                return;
            }

            try
            {
                if (RequestMessage == null)
                {
                    return;
                }


                #region NeuChar 执行过程

                var weixinAppId = this._postModel.AppId;

                switch (RequestMessage.MsgType)
                {
                case RequestMsgType.Text:
                {
                    try
                    {
                        var requestMessage = RequestMessage as RequestMessageText;
                        ResponseMessage = await CurrentMessageHandlerNode.ExecuteAsync(requestMessage, this, weixinAppId)
                                          ?? ((await(OnTextOrEventRequestAsync(requestMessage))
                                               ?? (await OnTextRequestAsync(requestMessage))));
                    }
                    catch (Exception ex)
                    {
                        SenparcTrace.SendCustomLog("mp-response error", ex.Message + "\r\n|||\r\n" + (ex.InnerException != null ? ex.InnerException.ToString() : ""));
                    }
                }
                break;

                case RequestMsgType.Location:
                    ResponseMessage = await OnLocationRequestAsync(RequestMessage as RequestMessageLocation);

                    break;

                case RequestMsgType.Image:

                    WeixinTrace.SendCustomLog("NeuChar Image", $"appid:{weixinAppId}");

                    ResponseMessage = await CurrentMessageHandlerNode.ExecuteAsync(RequestMessage, this, weixinAppId) ?? await OnImageRequestAsync(RequestMessage as RequestMessageImage);

                    break;

                case RequestMsgType.Voice:
                    ResponseMessage = await OnVoiceRequestAsync(RequestMessage as RequestMessageVoice);

                    break;

                case RequestMsgType.Video:
                    ResponseMessage = await OnVideoRequestAsync(RequestMessage as RequestMessageVideo);

                    break;

                case RequestMsgType.Link:
                    ResponseMessage = await OnLinkRequestAsync(RequestMessage as RequestMessageLink);

                    break;

                case RequestMsgType.ShortVideo:
                    ResponseMessage = await OnShortVideoRequestAsync(RequestMessage as RequestMessageShortVideo);

                    break;

                case RequestMsgType.File:
                    ResponseMessage = await OnFileRequestAsync(RequestMessage as RequestMessageFile);

                    break;

                case RequestMsgType.NeuChar:
                    ResponseMessage = await OnNeuCharRequestAsync(RequestMessage as RequestMessageNeuChar);

                    break;

                case RequestMsgType.Unknown:
                    ResponseMessage = await OnUnknownTypeRequestAsync(RequestMessage as RequestMessageUnknownType);

                    break;

                case RequestMsgType.Event:
                {
                    var requestMessageText = (RequestMessage as IRequestMessageEventBase).ConvertToRequestMessageText();
                    ResponseMessage = await CurrentMessageHandlerNode.ExecuteAsync(RequestMessage, this, weixinAppId) ??
                                      await OnTextOrEventRequestAsync(requestMessageText) ??
                                      (await OnEventRequestAsync(RequestMessage as IRequestMessageEventBase));
                }
                break;

                default:
                    Weixin.WeixinTrace.SendCustomLog("NeuChar", "未知的MsgType请求类型" + RequestMessage.MsgType);
                    //throw new UnknownRequestMsgTypeException("未知的MsgType请求类型", null);
                    break;
                }

                #endregion


                //记录上下文
                //此处修改
                if (MessageContextGlobalConfig.UseMessageContext && ResponseMessage != null && !string.IsNullOrEmpty(ResponseMessage.FromUserName))
                {
                    GlobalMessageContext.InsertMessage(ResponseMessage);
                }
            }
            catch (Exception ex)
            {
                throw new MessageHandlerException("MessageHandler中Execute()过程发生错误:" + ex.Message, ex);
            }
            finally
            {
                await OnExecutedAsync();
            }
        }