using Microsoft.AspNetCore.Http;
using System.Text;
using System.Threading.Tasks;

namespace CrazyStudio.Core.Pay.TenPay.Lib
{
    /// <summary>
    /// 回调处理基类
    /// 主要负责接收微信支付后台发送过来的数据，对数据进行签名验证
    /// 子类在此类基础上进行派生并重写自己的回调处理过程
    /// </summary>
    public class Notify
    {
        public HttpContext context { get; set; }
        public Notify(HttpContext page)
        {
            this.context = page;
        }

        /// <summary>
        /// 接收从微信支付后台发送过来的数据并验证签名
        /// </summary>
        /// <returns>微信支付后台返回的数据</returns>
        public async Task<WxPayData> GetNotifyData()
        {
            //接收从微信后台POST过来的数据
            System.IO.Stream s = context.Request.Body;
            int count = 0;
            byte[] buffer = new byte[1024];
            StringBuilder builder = new StringBuilder();
            while ((count = await s.ReadAsync(buffer, 0, 1024)) > 0)
            {
                builder.Append(Encoding.UTF8.GetString(buffer, 0, count));
            }
            await s.FlushAsync();
            s.Close();
            await s.DisposeAsync();

            Log.Info(this.GetType().ToString(), "Receive data from WeChat : " + builder.ToString());

            //转换数据格式并验证签名
            WxPayData data = new WxPayData();
            try
            {
                data.FromXml(builder.ToString());
            }
            catch (WxPayException ex)
            {
                //若签名错误，则立即返回结果给微信支付后台
                WxPayData res = new WxPayData();
                res.SetValue("return_code", "FAIL");
                res.SetValue("return_msg", ex.Message);

                var xml = res.ToXml();
                Log.Error(this.GetType().ToString(), "Sign check error : " + res.ToXml());
                var send = Encoding.UTF8.GetBytes(xml);
                await context.Response.Body.WriteAsync(send, 0, send.Length);
                await context.Response.Body.FlushAsync();
                return null;
            }

            Log.Info(this.GetType().ToString(), "Check sign success");
            return data;
        }

        //派生类需要重写这个方法，进行不同的回调处理
        public virtual Task<WxPayData> ProcessNotify()
        {
            return null;
        }
    }
}