BrnShop開源網上商城第四講:自定義插件

重要通知:BrnShop企業版NOSQL設計(基於Redis)已經開源!源碼內置於最新版的BrnShop中,感興趣的園友能夠去下載來看看。官網地址:www.brnshop.comhtml

  好了如今進入今天的正題:自定義插件。上一講中咱們已經闡述了BrnShop插件的工做機制,如今咱們詳細介紹下如何自定義插件。首先BrnShop的插件從功能上分爲三類,分別是:數組

  • 開放受權插件(OAuth)
  • 支付插件
  • 配送插件

  對應的接口文件(注:位於BrnShop.Core項目的Plugin/Base文件夾中)依次以下:安全

  • IOAuthPlugin
  • IPayPlugin
  • IShipPlugin

  如今咱們依次介紹下各個接口,首先登場的是IOAuthPlugin接口。先看它的定義:服務器

複製代碼
    /// <summary>
    /// BrnShop開放受權插件接口
    /// </summary>
    public interface IOAuthPlugin : IPlugin
    {
        /// <summary>
        /// 登錄控制器
        /// </summary>
        string LoginController { get; }

        /// <summary>
        /// 登錄動做方法
        /// </summary>
        string LoginAction { get; }

        /// <summary>
        /// 登錄路由數據
        /// </summary>
        RouteValueDictionary LoginRouteValues { get; }
    }
複製代碼

  對於一個開放受權插件來講,它只須要向主應用程序提供本身的一個登錄地址就能夠,至於怎麼受權驗證等那都是插件本身的事情了。因此IOAuthPlugin接口內容僅僅是登錄地址的mvc3要素(控制器名,動做方法名,路由數據)就能夠了,以QQ受權登錄爲例:mvc

  

  接下來是IPayPlugin接口,代碼以下:框架

/// <summary>
/// BrnShop支付插件接口
/// </summary>
public interface IPayPlugin : IPlugin
{
/// <summary>
/// 付款方式(0表明貨到付款,1表明在線付款,2表明線下付款)
/// </summary>
int PayMode { get; }異步

/// <summary>
/// 是否容許帳戶充值(只對在線付款有效)
/// </summary>
bool AllowRecharge { get; }ide

/// <summary>
/// 支付返回控制器
/// </summary>
string ReturnController { get; }函數

/// <summary>
/// 支付返回動做方法
/// </summary>
string ReturnAction { get; }工具

/// <summary>
/// 支付返回路由數據
/// </summary>
RouteValueDictionary ReturnRouteValues { get; }

/// <summary>
/// 支付通知控制器
/// </summary>
string NotifyController { get; }

/// <summary>
/// 支付通知動做方法
/// </summary>
string NotifyAction { get; }

/// <summary>
/// 支付通知路由數據
/// </summary>
RouteValueDictionary NotifyRouteValues { get; }

/// <summary>
/// 得到支付手續費
/// </summary>
/// <param name="productAmount">商品合計</param>
/// <param name="buyTime">購買時間</param>
/// <param name="partUserInfo">購買用戶</param>
/// <returns></returns>
decimal GetPayFee(decimal productAmount, DateTime buyTime, PartUserInfo partUserInfo);

/// <summary>
/// 若是付款方式爲在線付款則返回付款請求的url,不然返回空字符串
/// </summary>
/// <param name="returnUrl">返回url</param>
/// <param name="notifyUrl">通知url</param>
/// <param name="pluginInfo">插件信息</param>
/// <param name="partUserInfo">購買用戶</param>
/// <param name="orderInfo">訂單信息</param>
/// <returns></returns>
string GetRequestUrl(string returnUrl, string notifyUrl, PluginInfo pluginInfo, PartUserInfo partUserInfo, OrderInfo orderInfo);
}


複製代碼
/// <summary>
    /// BrnShop支付插件接口
    /// </summary>
    public interface IPayPlugin : IPlugin
    {
        /// <summary>
        /// 付款方式(0表明貨到付款,1表明在線付款,2表明線下付款)
        /// </summary>
        int PayMode { get; }

        /// <summary>
        /// 是否容許帳戶充值(只對在線付款有效)
        /// </summary>
        bool AllowRecharge { get; }

        /// <summary>
        /// 支付返回控制器
        /// </summary>
        string ReturnController { get; }

        /// <summary>
        /// 支付返回動做方法
        /// </summary>
        string ReturnAction { get; }

        /// <summary>
        /// 支付返回路由數據
        /// </summary>
        RouteValueDictionary ReturnRouteValues { get; }

        /// <summary>
        /// 支付通知控制器
        /// </summary>
        string NotifyController { get; }

        /// <summary>
        /// 支付通知動做方法
        /// </summary>
        string NotifyAction { get; }

        /// <summary>
        /// 支付通知路由數據
        /// </summary>
        RouteValueDictionary NotifyRouteValues { get; }

        /// <summary>
        /// 得到支付手續費
        /// </summary>
        /// <param name="productAmount">商品合計</param>
        /// <param name="buyTime">購買時間</param>
        /// <param name="partUserInfo">購買用戶</param>
        /// <returns></returns>
        decimal GetPayFee(decimal productAmount, DateTime buyTime, PartUserInfo partUserInfo);

        /// <summary>
        /// 若是付款方式爲在線付款則返回付款請求的url,不然返回空字符串
        /// </summary>
        /// <param name="returnUrl">返回url</param>
        /// <param name="notifyUrl">通知url</param>
        /// <param name="pluginInfo">插件信息</param>
        /// <param name="partUserInfo">購買用戶</param>
        /// <param name="orderInfo">訂單信息</param>
        /// <returns></returns>
        string GetRequestUrl(string returnUrl, string notifyUrl, PluginInfo pluginInfo, PartUserInfo partUserInfo, OrderInfo orderInfo);
    }
複製代碼

  成員比較多,咱們分類來看就清晰了:

  • PayMode:表明支付的3種類型,這個屬性很是重要,由於其它成員的實現跟他密切相關。
  • GetPayFee:計算訂單的支付手續費。
  • GetRequestUrl:只在PayMode爲在線付款時有效;返回支付地址,在BrnShop.Web項目的OrderController類的PayShow方法中調用。
  • ReturnController,ReturnAction,ReturnRouteValues:這3個成員爲一組,而且只在PayMode爲在線付款時有效;提供支付完成後的返回地址。
  • NotifyController,NotifyAction,NotifyRouteValues:這3個成員爲一組,而且只在PayMode爲在線付款時有效;提供支付完成後的回調地址。
  • AllowRecharge:系統預留成員,目前無用。

  最後咱們來看下IShipPlugin接口,代碼以下:

複製代碼
    /// <summary>
    /// BrnShop配送插件接口
    /// </summary>
    public interface IShipPlugin : IPlugin
    {
        /// <summary>
        /// 得到配送費用
        /// </summary>
        /// <param name="totalWeight">訂單總重量</param>
        /// <param name="productAmount">商品合計</param>
        /// <param name="buyTime">購買時間</param>
        /// <param name="shipRegionId">收貨區域</param>
        /// <param name="partUserInfo">購買用戶</param>
        /// <returns></returns>
        decimal GetShipFee(int totalWeight, decimal productAmount, DateTime buyTime, int shipRegionId, PartUserInfo partUserInfo);
    }
複製代碼

  這個接口比較簡單,只是提供一個計算配送費用的成員。

  補充說明一下:以上3個接口都繼承自IPlugin,這個接口提供後臺配置地址mvc3要素,只在BrnShop.Web.Admin項目中的插件配置視圖中使用,具體以下:

複製代碼
    @if (Model.ConfigRouteValues == null)
    {
        @Html.Action(Model.ConfigAction, Model.ConfigController)
    }
    else
    {
        @Html.Action(Model.ConfigAction, Model.ConfigController, Model.ConfigRouteValues)
    }
複製代碼

   下面咱們以支付寶插件爲例來說解下如何自定義一個插件。

   首先新建一個ASP.NET MVC3應用程序並引用須要的程序集,根據上一篇講解咱們知道須要修改非.net自帶程序集的複製到本地屬性和項目生成屬性。具體以下圖:

  至此咱們的項目基本框架已經搭好了。如今咱們須要添加一個插件說明文件(注:此文件爲必須文件且文件名稱必須爲PluginInfo.config,還有不要忘記修改它的複製屬性)。內容以下:

複製代碼
<?xml version="1.0" encoding="utf-8"?>
<PluginInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <SystemName>alipay</SystemName>
  <FriendlyName>支付寶</FriendlyName>
  <ClassFullName>BrnShop.PayPlugin.Alipay.PluginService,BrnShop.PayPlugin.Alipay</ClassFullName>
  <Folder>BrnShop.PayPlugin.Alipay</Folder>
  <Description>阿里巴巴旗下支付工具</Description>
  <Type>1</Type>
  <Author>brnshop</Author>
  <Version>1.0</Version>
  <SupVersion>1.0.0</SupVersion>
  <DisplayOrder>3</DisplayOrder>
  <IsDefault>0</IsDefault>
</PluginInfo>
複製代碼

  這個文件是BrnShop.Core項目中的PluginInfo序列化文件,因此節點說明請參考下面代碼:

/// <summary>
/// 插件信息類
/// </summary>
public class PluginInfo : IComparable
{
private string _systemname = "";//插件系統名稱(必須具備惟一性)
private string _friendlyname = "";//插件友好名稱
private string _classfullname = "";//插件控制器
private string _folder = "";//插件目錄
private string _description = "";//插件描述
private int _type = 0;//插件類型(0表明開放受權插件,1表明支付插件,2表明配送插件)
private string _author = "";//插件做者
private string _version = "";//插件版本
private string _supversion = "";//插件支持的BrnShop版本
private int _displayOrder = 0;//插件順序
private int _isdefault = 0;//是不是默認插件

/// <summary>
/// 插件系統名稱
/// </summary>
public string SystemName
{
get { return _systemname; }
set { _systemname = value; }
}

/// <summary>
/// 插件友好名稱
/// </summary>
public string FriendlyName
{
get { return _friendlyname; }
set { _friendlyname = value; }
}

/// <summary>
/// 插件類型名稱
/// </summary>
public string ClassFullName
{
get { return _classfullname; }
set { _classfullname = value; }
}

/// <summary>
/// 插件目錄
/// </summary>
public string Folder
{
get { return _folder; }
set { _folder = value; }
}

/// <summary>
/// 插件描述
/// </summary>
public string Description
{
get { return _description; }
set { _description = value; }
}

/// <summary>
/// 插件類型(0表明開放受權插件,1表明支付插件,2表明配送插件)
/// </summary>
public int Type
{
get { return _type; }
set { _type = value; }
}

/// <summary>
/// 插件做者
/// </summary>
public string Author
{
get { return _author; }
set { _author = value; }
}

/// <summary>
/// 插件版本
/// </summary>
public string Version
{
get { return _version; }
set { _version = value; }
}

/// <summary>
/// 插件支持的BrnShop版本
/// </summary>
public string SupVersion
{
get { return _supversion; }
set { _supversion = value; }
}

/// <summary>
/// 插件順序
/// </summary>
public int DisplayOrder
{
get { return _displayOrder; }
set { _displayOrder = value; }
}

/// <summary>
/// 是不是默認插件
/// </summary>
public int IsDefault
{
get { return _isdefault; }
set { _isdefault = value; }
}


/// <summary>
/// 插件實例
/// </summary>
private IPlugin _instance = null;

/// <summary>
/// 插件實例
/// </summary>
[XmlIgnoreAttribute]
public IPlugin Instance
{
get
{
if (_instance == null)
{
try
{
_instance = (IPlugin)Activator.CreateInstance(System.Type.GetType(ClassFullName, false, true));
}
catch (Exception ex)
{
throw new BSPException("建立插件:" + _classfullname + "的實例失敗", ex);
}
}
return _instance;
}
}

public int CompareTo(object obj)
{
PluginInfo info = (PluginInfo)obj;

if (this.DisplayOrder > info.DisplayOrder)
return 1;
else if (this.DisplayOrder < info.DisplayOrder)
return -1;
else
return 0;
}

}

複製代碼
/// <summary>
    /// 插件信息類
    /// </summary>
    public class PluginInfo : IComparable
    {
        private string _systemname = "";//插件系統名稱(必須具備惟一性)
        private string _friendlyname = "";//插件友好名稱
        private string _classfullname = "";//插件控制器
        private string _folder = "";//插件目錄
        private string _description = "";//插件描述
        private int _type = 0;//插件類型(0表明開放受權插件,1表明支付插件,2表明配送插件)
        private string _author = "";//插件做者
        private string _version = "";//插件版本
        private string _supversion = "";//插件支持的BrnShop版本
        private int _displayOrder = 0;//插件順序
        private int _isdefault = 0;//是不是默認插件

        /// <summary>
        /// 插件系統名稱
        /// </summary>
        public string SystemName
        {
            get { return _systemname; }
            set { _systemname = value; }
        }

        /// <summary>
        /// 插件友好名稱
        /// </summary>
        public string FriendlyName
        {
            get { return _friendlyname; }
            set { _friendlyname = value; }
        }

        /// <summary>
        /// 插件類型名稱
        /// </summary>
        public string ClassFullName
        {
            get { return _classfullname; }
            set { _classfullname = value; }
        }

        /// <summary>
        /// 插件目錄
        /// </summary>
        public string Folder
        {
            get { return _folder; }
            set { _folder = value; }
        }

        /// <summary>
        /// 插件描述
        /// </summary>
        public string Description
        {
            get { return _description; }
            set { _description = value; }
        }

        /// <summary>
        /// 插件類型(0表明開放受權插件,1表明支付插件,2表明配送插件)
        /// </summary>
        public int Type
        {
            get { return _type; }
            set { _type = value; }
        }

        /// <summary>
        /// 插件做者
        /// </summary>
        public string Author
        {
            get { return _author; }
            set { _author = value; }
        }

        /// <summary>
        /// 插件版本
        /// </summary>
        public string Version
        {
            get { return _version; }
            set { _version = value; }
        }

        /// <summary>
        /// 插件支持的BrnShop版本
        /// </summary>
        public string SupVersion
        {
            get { return _supversion; }
            set { _supversion = value; }
        }

        /// <summary>
        /// 插件順序
        /// </summary>
        public int DisplayOrder
        {
            get { return _displayOrder; }
            set { _displayOrder = value; }
        }

        /// <summary>
        /// 是不是默認插件
        /// </summary>
        public int IsDefault
        {
            get { return _isdefault; }
            set { _isdefault = value; }
        }


        /// <summary>
        /// 插件實例
        /// </summary>
        private IPlugin _instance = null;

        /// <summary>
        /// 插件實例
        /// </summary>
        [XmlIgnoreAttribute]
        public IPlugin Instance
        {
            get
            {
                if (_instance == null)
                {
                    try
                    {
                        _instance = (IPlugin)Activator.CreateInstance(System.Type.GetType(ClassFullName, false, true));
                    }
                    catch (Exception ex)
                    {
                        throw new BSPException("建立插件:" + _classfullname + "的實例失敗", ex);
                    }
                }
                return _instance;
            }
        }

        public int CompareTo(object obj)
        {
            PluginInfo info = (PluginInfo)obj;

            if (this.DisplayOrder > info.DisplayOrder)
                return 1;
            else if (this.DisplayOrder < info.DisplayOrder)
                return -1;
            else
                return 0;
        }

    }
複製代碼

  接下來咱們定義一個類PluginService,並實現接口IPayPlugin,代碼以下:

/// <summary>
/// 插件服務類
/// </summary>
public class PluginService : IPayPlugin
{
/// <summary>
/// 插件配置控制器
/// </summary>
/// <value></value>
public string ConfigController
{
get { return "AdminAlipay"; }
}
/// <summary>
/// 插件配置動做方法
/// </summary>
/// <value></value>
public string ConfigAction
{
get { return "Config"; }
}
/// <summary>
/// 插件配置路由數據
/// </summary>
/// <value></value>
public RouteValueDictionary ConfigRouteValues
{
get { return new RouteValueDictionary() { { "area", "Admin" } }; }
}
/// <summary>
/// 付款方式(0表明貨到付款,1表明在線付款,2表明線下付款)
/// </summary>
/// <value></value>
public int PayMode
{
get { return 1; }
}
/// <summary>
/// 是否容許帳戶充值(只對在線付款有效)
/// </summary>
/// <value></value>
public bool AllowRecharge
{
get { return PluginUtils.GetPluginSet().AllowRecharge == 1; }
}
/// <summary>
/// 支付返回控制器
/// </summary>
/// <value></value>
public string ReturnController
{
get { return "Alipay"; }
}
/// <summary>
/// 支付返回動做方法
/// </summary>
/// <value></value>
public string ReturnAction
{
get { return "Return"; }
}
/// <summary>
/// 支付返回路由數據
/// </summary>
/// <value></value>
public RouteValueDictionary ReturnRouteValues
{
get { return null; }
}
/// <summary>
/// 支付通知控制器
/// </summary>
/// <value></value>
public string NotifyController
{
get { return "Alipay"; }
}
/// <summary>
/// 支付通知動做方法
/// </summary>
/// <value></value>
public string NotifyAction
{
get { return "Notify"; }
}
/// <summary>
/// 支付通知路由數據
/// </summary>
/// <value></value>
public RouteValueDictionary NotifyRouteValues
{
get { return null; }
}
/// <summary>
/// 得到支付手續費
/// </summary>
/// <param name="productAmount">商品合計</param>
/// <param name="buyTime">購買時間</param>
/// <param name="partUserInfo">購買用戶</param>
/// <returns></returns>
public decimal GetPayFee(decimal productAmount, DateTime buyTime, PartUserInfo partUserInfo)
{
return 0M;
}
/// <summary>
/// 若是付款方式爲在線付款則返回付款請求的url,不然返回空字符串
/// </summary>
/// <param name="notifyUrl">通知url</param>
/// <param name="returnUrl">返回url</param>
/// <param name="pluginInfo">插件信息</param>
/// <param name="partUserInfo">購買用戶</param>
/// <param name="orderInfo">訂單信息</param>
/// <returns></returns>
public string GetRequestUrl(string notifyUrl, string returnUrl, PluginInfo pluginInfo, PartUserInfo partUserInfo, OrderInfo orderInfo)
{
//支付類型,必填,不能修改
string paymentType = "1";

//服務器異步通知頁面路徑,需http://格式的完整路徑,不能加?id=123這類自定義參數
notifyUrl = string.Format("http://{0}{1}", BSPConfig.ShopConfig.SiteUrl, notifyUrl);

//頁面跳轉同步通知頁面路徑,需http://格式的完整路徑,不能加?id=123這類自定義參數,不能寫成http://localhost/
returnUrl = string.Format("http://{0}{1}", BSPConfig.ShopConfig.SiteUrl, returnUrl);

//收款支付寶賬戶
string sellerEmail = AlipayConfig.Seller;

//合做者身份ID
string partner = AlipayConfig.Partner;

//交易安全檢驗碼
string key = AlipayConfig.Key;

//商戶訂單號
string outTradeNo = orderInfo.Oid.ToString();

//訂單名稱
string subject = "";

//付款金額
string totalFee = orderInfo.SurplusMoney.ToString();

//訂單描述
string body = "";

//防釣魚時間戳,若要使用請調用類文件submit中的query_timestamp函數
string anti_phishing_key = "";

//客戶端的IP地址,非局域網的外網IP地址,如:221.0.0.1
string exter_invoke_ip = "";

//把請求參數打包成數組
SortedDictionary<string, string> sParaTemp = new SortedDictionary<string, string>();
sParaTemp.Add("partner", partner);
sParaTemp.Add("_input_charset", key);
sParaTemp.Add("service", "create_direct_pay_by_user");
sParaTemp.Add("payment_type", paymentType);
sParaTemp.Add("notify_url", notifyUrl);
sParaTemp.Add("return_url", returnUrl);
sParaTemp.Add("seller_email", sellerEmail);
sParaTemp.Add("out_trade_no", outTradeNo);
sParaTemp.Add("subject", subject);
sParaTemp.Add("total_fee", totalFee);
sParaTemp.Add("body", body);
sParaTemp.Add("anti_phishing_key", anti_phishing_key);
sParaTemp.Add("exter_invoke_ip", exter_invoke_ip);

return AlipaySubmit.BuildRequestUrl(sParaTemp, AlipayConfig.Gateway, AlipayConfig.InputCharset, AlipayConfig.SignType, AlipayConfig.Key, AlipayConfig.Code);
}
}

複製代碼
/// <summary>
    /// 插件服務類
    /// </summary>
    public class PluginService : IPayPlugin
    {
        /// <summary>
        /// 插件配置控制器
        /// </summary>
        /// <value></value>
        public string ConfigController
        {
            get { return "AdminAlipay"; }
        }
        /// <summary>
        /// 插件配置動做方法
        /// </summary>
        /// <value></value>
        public string ConfigAction
        {
            get { return "Config"; }
        }
        /// <summary>
        /// 插件配置路由數據
        /// </summary>
        /// <value></value>
        public RouteValueDictionary ConfigRouteValues
        {
            get { return new RouteValueDictionary() { { "area", "Admin" } }; }
        }
        /// <summary>
        /// 付款方式(0表明貨到付款,1表明在線付款,2表明線下付款)
        /// </summary>
        /// <value></value>
        public int PayMode
        {
            get { return 1; }
        }
        /// <summary>
        /// 是否容許帳戶充值(只對在線付款有效)
        /// </summary>
        /// <value></value>
        public bool AllowRecharge
        {
            get { return PluginUtils.GetPluginSet().AllowRecharge == 1; }
        }
        /// <summary>
        /// 支付返回控制器
        /// </summary>
        /// <value></value>
        public string ReturnController
        {
            get { return "Alipay"; }
        }
        /// <summary>
        /// 支付返回動做方法
        /// </summary>
        /// <value></value>
        public string ReturnAction
        {
            get { return "Return"; }
        }
        /// <summary>
        /// 支付返回路由數據
        /// </summary>
        /// <value></value>
        public RouteValueDictionary ReturnRouteValues
        {
            get { return null; }
        }
        /// <summary>
        /// 支付通知控制器
        /// </summary>
        /// <value></value>
        public string NotifyController
        {
            get { return "Alipay"; }
        }
        /// <summary>
        /// 支付通知動做方法
        /// </summary>
        /// <value></value>
        public string NotifyAction
        {
            get { return "Notify"; }
        }
        /// <summary>
        /// 支付通知路由數據
        /// </summary>
        /// <value></value>
        public RouteValueDictionary NotifyRouteValues
        {
            get { return null; }
        }
        /// <summary>
        /// 得到支付手續費
        /// </summary>
        /// <param name="productAmount">商品合計</param>
        /// <param name="buyTime">購買時間</param>
        /// <param name="partUserInfo">購買用戶</param>
        /// <returns></returns>
        public decimal GetPayFee(decimal productAmount, DateTime buyTime, PartUserInfo partUserInfo)
        {
            return 0M;
        }
        /// <summary>
        /// 若是付款方式爲在線付款則返回付款請求的url,不然返回空字符串
        /// </summary>
        /// <param name="notifyUrl">通知url</param>
        /// <param name="returnUrl">返回url</param>
        /// <param name="pluginInfo">插件信息</param>
        /// <param name="partUserInfo">購買用戶</param>
        /// <param name="orderInfo">訂單信息</param>
        /// <returns></returns>
        public string GetRequestUrl(string notifyUrl, string returnUrl, PluginInfo pluginInfo, PartUserInfo partUserInfo, OrderInfo orderInfo)
        {
            //支付類型,必填,不能修改
            string paymentType = "1";

            //服務器異步通知頁面路徑,需http://格式的完整路徑,不能加?id=123這類自定義參數
            notifyUrl = string.Format("http://{0}{1}", BSPConfig.ShopConfig.SiteUrl, notifyUrl);

            //頁面跳轉同步通知頁面路徑,需http://格式的完整路徑,不能加?id=123這類自定義參數,不能寫成http://localhost/
            returnUrl = string.Format("http://{0}{1}", BSPConfig.ShopConfig.SiteUrl, returnUrl);

            //收款支付寶賬戶
            string sellerEmail = AlipayConfig.Seller;

            //合做者身份ID
            string partner = AlipayConfig.Partner;

            //交易安全檢驗碼
            string key = AlipayConfig.Key;

            //商戶訂單號
            string outTradeNo = orderInfo.Oid.ToString();

            //訂單名稱
            string subject = "";

            //付款金額
            string totalFee = orderInfo.SurplusMoney.ToString();

            //訂單描述
            string body = "";

            //防釣魚時間戳,若要使用請調用類文件submit中的query_timestamp函數
            string anti_phishing_key = "";

            //客戶端的IP地址,非局域網的外網IP地址,如:221.0.0.1
            string exter_invoke_ip = "";

            //把請求參數打包成數組
            SortedDictionary<string, string> sParaTemp = new SortedDictionary<string, string>();
            sParaTemp.Add("partner", partner);
            sParaTemp.Add("_input_charset", key);
            sParaTemp.Add("service", "create_direct_pay_by_user");
            sParaTemp.Add("payment_type", paymentType);
            sParaTemp.Add("notify_url", notifyUrl);
            sParaTemp.Add("return_url", returnUrl);
            sParaTemp.Add("seller_email", sellerEmail);
            sParaTemp.Add("out_trade_no", outTradeNo);
            sParaTemp.Add("subject", subject);
            sParaTemp.Add("total_fee", totalFee);
            sParaTemp.Add("body", body);
            sParaTemp.Add("anti_phishing_key", anti_phishing_key);
            sParaTemp.Add("exter_invoke_ip", exter_invoke_ip);

            return AlipaySubmit.BuildRequestUrl(sParaTemp, AlipayConfig.Gateway, AlipayConfig.InputCharset, AlipayConfig.SignType, AlipayConfig.Key, AlipayConfig.Code);
        }
    }
複製代碼

  由於支付寶有一些須要配置的屬性要保存,例如收款支付寶賬戶等。在此咱們採用對象序列化和文件的方式來保存這些信息。首先定義一個設置信息類,代碼以下:

/// <summary>
/// 插件設置信息類
/// </summary>
public class PluginSetInfo
{
private string _partner;//合做者身份ID
private string _key;//交易安全檢驗碼
private string _seller;//收款支付寶賬戶
private int _allowrecharge;//是否容許帳戶充值

/// <summary>
/// 合做者身份ID
/// </summary>
public string Partner
{
get { return _partner; }
set { _partner = value; }
}

/// <summary>
/// 交易安全檢驗碼
/// </summary>
public string Key
{
get { return _key; }
set { _key = value; }
}

/// <summary>
/// 收款支付寶賬戶
/// </summary>
public string Seller
{
get { return _seller; }
set { _seller = value; }
}

/// <summary>
/// 是否容許帳戶充值
/// </summary>
public int AllowRecharge
{
get { return _allowrecharge; }
set { _allowrecharge = value; }
}
}

複製代碼
/// <summary>
    /// 插件設置信息類
    /// </summary>
    public class PluginSetInfo
    {
        private string _partner;//合做者身份ID
        private string _key;//交易安全檢驗碼
        private string _seller;//收款支付寶賬戶
        private int _allowrecharge;//是否容許帳戶充值

        /// <summary>
        /// 合做者身份ID
        /// </summary>
        public string Partner
        {
            get { return _partner; }
            set { _partner = value; }
        }

        /// <summary>
        /// 交易安全檢驗碼
        /// </summary>
        public string Key
        {
            get { return _key; }
            set { _key = value; }
        }

        /// <summary>
        /// 收款支付寶賬戶
        /// </summary>
        public string Seller
        {
            get { return _seller; }
            set { _seller = value; }
        }

        /// <summary>
        /// 是否容許帳戶充值
        /// </summary>
        public int AllowRecharge
        {
            get { return _allowrecharge; }
            set { _allowrecharge = value; }
        }
    }
複製代碼

  而後添加一個工具類PluginUtils來序列化和反序列化設置信息,代碼以下:

/// <summary>
/// 插件工具類
/// </summary>
public class PluginUtils
{
private static object _locker = new object();//鎖對象
private static PluginSetInfo _pluginsetinfo = null;//插件設置信息
private static string _plugindatafilepath = "/Plugins/BrnShop.PayPlugin.Alipay/PluginData.config";//數據文件路徑

/// <summary>
///得到插件設置
/// </summary>
/// <returns></returns>
public static PluginSetInfo GetPluginSet()
{
if (_pluginsetinfo == null)
{
lock (_locker)
{
if (_pluginsetinfo == null)
{
_pluginsetinfo = (PluginSetInfo)IOHelper.DeserializeFromXML(typeof(PluginSetInfo), IOHelper.GetMapPath(_plugindatafilepath));
}
}
}
return _pluginsetinfo;
}

/// <summary>
/// 保存插件設置到數據數據文件中
/// </summary>
public static void SavePluginSet(PluginSetInfo pluginSetInfo)
{
lock (_locker)
{
IOHelper.SerializeToXml(pluginSetInfo, IOHelper.GetMapPath(_plugindatafilepath));
_pluginsetinfo = null;
AlipayConfig.ReSet();
}
}

}

複製代碼
/// <summary>
    /// 插件工具類
    /// </summary>
    public class PluginUtils
    {
        private static object _locker = new object();//鎖對象
        private static PluginSetInfo _pluginsetinfo = null;//插件設置信息
        private static string _plugindatafilepath = "/Plugins/BrnShop.PayPlugin.Alipay/PluginData.config";//數據文件路徑

        /// <summary>
        ///得到插件設置
        /// </summary>
        /// <returns></returns>
        public static PluginSetInfo GetPluginSet()
        {
            if (_pluginsetinfo == null)
            {
                lock (_locker)
                {
                    if (_pluginsetinfo == null)
                    {
                        _pluginsetinfo = (PluginSetInfo)IOHelper.DeserializeFromXML(typeof(PluginSetInfo), IOHelper.GetMapPath(_plugindatafilepath));
                    }
                }
            }
            return _pluginsetinfo;
        }

        /// <summary>
        /// 保存插件設置到數據數據文件中
        /// </summary>
        public static void SavePluginSet(PluginSetInfo pluginSetInfo)
        {
            lock (_locker)
            {
                IOHelper.SerializeToXml(pluginSetInfo, IOHelper.GetMapPath(_plugindatafilepath));
                _pluginsetinfo = null;
                AlipayConfig.ReSet();
            }
        }

    }
複製代碼

   就下來就是前臺和後臺實現了。首先是後臺實現,對於後臺咱們只須要提供一個可供修改支付寶配置的子方法就好了,此子方法在上面講解"IPlugin"接口時已經給出了它的調用方式。代碼以下:


複製代碼
/// <summary>
        /// 通知調用
        /// </summary>
        public ActionResult Notify()
        {
            SortedDictionary<string, string> sPara = AlipayCore.GetRequestPost();

            if (sPara.Count > 0)//判斷是否有帶返回參數
            {
                bool verifyResult = AlipayNotify.Verify(sPara, Request.QueryString["notify_id"], Request.QueryString["sign"], AlipayConfig.SignType, AlipayConfig.Key, AlipayConfig.Code, AlipayConfig.VeryfyUrl, AlipayConfig.Partner);

                if (verifyResult && (Request.QueryString["trade_status"] == "TRADE_FINISHED" || Request.QueryString["trade_status"] == "TRADE_SUCCESS"))//驗證成功
                {
                    int oid = TypeHelper.StringToInt(Request.QueryString["out_trade_no"]);//商戶訂單號
                    string tradeSN = Request.QueryString["trade_no"];//支付寶交易號
                    decimal tradeMoney = TypeHelper.StringToDecimal(Request.QueryString["total_fee"]);//交易金額
                    DateTime tradeTime = TypeHelper.StringToDateTime(Request.QueryString["gmt_payment"]);//交易時間

                    OrderInfo orderInfo = Orders.GetOrderByOid(oid);
                    if (orderInfo.PayMode == 1 && orderInfo.SurplusMoney > 0 && orderInfo.SurplusMoney <= tradeMoney)
                    {
                        Orders.PayOrder(oid, OrderState.Confirming, tradeSN);
                        OrderActions.CreateOrderAction(new OrderActionInfo()
                        {
                            Oid = oid,
                            Uid = orderInfo.Uid,
                            RealName = "本人",
                            AdminGid = 1,
                            AdminGTitle = "非管理員",
                            ActionType = (int)OrderActionType.Pay,
                            ActionTime = tradeTime,
                            ActionDes = "你使用支付寶支付訂單成功,支付寶交易號爲:" + tradeSN
                        });
                    }

                    return new EmptyResult();
                }
                else//驗證失敗
                {
                    return new EmptyResult();
                }
            }
            else
            {
                return new EmptyResult();
            }
        }
複製代碼
    /// <summary>
    /// 後臺支付寶插件控制器類
    /// </summary>
    public class AdminAlipayController : BaseAdminController
    {
        /// <summary>
        /// 配置
        /// </summary>
        [HttpGet]
        [ChildActionOnly]
        public ActionResult Config()
        {
            ConfigModel model = new ConfigModel();

            model.Partner = PluginUtils.GetPluginSet().Partner;
            model.Key = PluginUtils.GetPluginSet().Key;
            model.Seller = PluginUtils.GetPluginSet().Seller;
            model.AllowRecharge = PluginUtils.GetPluginSet().AllowRecharge;

            return View("~/Plugins/BrnShop.PayPlugin.Alipay/Views/AdminAlipay/Config.cshtml", model);
        }

        /// <summary>
        /// 配置
        /// </summary>
        [HttpPost]
        public ActionResult Config(ConfigModel model)
        {
            if (ModelState.IsValid)
            {
                PluginSetInfo setting = new PluginSetInfo();

                setting.Partner = model.Partner.Trim();
                setting.Key = model.Key.Trim();
                setting.Seller = model.Seller.Trim();
                setting.AllowRecharge = model.AllowRecharge;

                PluginUtils.SavePluginSet(setting);
            }
            return RedirectToAction("List", "Plugin", new RouteValueDictionary() { { "area", "Admin" }, { "Type", "1" } });
        }
    }
複製代碼

  至於前臺咱們有3個方面須要去實現,第一個方面是返回調用動做方法,代碼以下:


複製代碼
/// <summary>
        /// 通知調用
        /// </summary>
        public ActionResult Notify()
        {
            SortedDictionary<string, string> sPara = AlipayCore.GetRequestPost();

            if (sPara.Count > 0)//判斷是否有帶返回參數
            {
                bool verifyResult = AlipayNotify.Verify(sPara, Request.QueryString["notify_id"], Request.QueryString["sign"], AlipayConfig.SignType, AlipayConfig.Key, AlipayConfig.Code, AlipayConfig.VeryfyUrl, AlipayConfig.Partner);

                if (verifyResult && (Request.QueryString["trade_status"] == "TRADE_FINISHED" || Request.QueryString["trade_status"] == "TRADE_SUCCESS"))//驗證成功
                {
                    int oid = TypeHelper.StringToInt(Request.QueryString["out_trade_no"]);//商戶訂單號
                    string tradeSN = Request.QueryString["trade_no"];//支付寶交易號
                    decimal tradeMoney = TypeHelper.StringToDecimal(Request.QueryString["total_fee"]);//交易金額
                    DateTime tradeTime = TypeHelper.StringToDateTime(Request.QueryString["gmt_payment"]);//交易時間

                    OrderInfo orderInfo = Orders.GetOrderByOid(oid);
                    if (orderInfo.PayMode == 1 && orderInfo.SurplusMoney > 0 && orderInfo.SurplusMoney <= tradeMoney)
                    {
                        Orders.PayOrder(oid, OrderState.Confirming, tradeSN);
                        OrderActions.CreateOrderAction(new OrderActionInfo()
                        {
                            Oid = oid,
                            Uid = orderInfo.Uid,
                            RealName = "本人",
                            AdminGid = 1,
                            AdminGTitle = "非管理員",
                            ActionType = (int)OrderActionType.Pay,
                            ActionTime = tradeTime,
                            ActionDes = "你使用支付寶支付訂單成功,支付寶交易號爲:" + tradeSN
                        });
                    }

                    return new EmptyResult();
                }
                else//驗證失敗
                {
                    return new EmptyResult();
                }
            }
            else
            {
                return new EmptyResult();
            }
        }
複製代碼
/// <summary>
        /// 返回調用
        /// </summary>
        public ActionResult Return()
        {
            SortedDictionary<string, string> sPara = AlipayCore.GetRequestGet();

            if (sPara.Count > 0)//判斷是否有帶返回參數
            {
                bool verifyResult = AlipayNotify.Verify(sPara, Request.QueryString["notify_id"], Request.QueryString["sign"], AlipayConfig.SignType, AlipayConfig.Key, AlipayConfig.Code, AlipayConfig.VeryfyUrl, AlipayConfig.Partner);

                if (verifyResult && (Request.QueryString["trade_status"] == "TRADE_FINISHED" || Request.QueryString["trade_status"] == "TRADE_SUCCESS"))//驗證成功
                {
                    int oid = TypeHelper.StringToInt(Request.QueryString["out_trade_no"]);//商戶訂單號
                    string tradeSN = Request.QueryString["trade_no"];//支付寶交易號
                    decimal tradeMoney = TypeHelper.StringToDecimal(Request.QueryString["total_fee"]);//交易金額
                    DateTime tradeTime = TypeHelper.StringToDateTime(Request.QueryString["notify_time"]);//交易時間

                    OrderInfo orderInfo = Orders.GetOrderByOid(oid);
                    if (orderInfo.PayMode == 1 && orderInfo.SurplusMoney > 0 && orderInfo.SurplusMoney <= tradeMoney)
                    {
                        Orders.PayOrder(oid, OrderState.Confirming, tradeSN);
                        OrderActions.CreateOrderAction(new OrderActionInfo()
                        {
                            Oid = oid,
                            Uid = orderInfo.Uid,
                            RealName = "本人",
                            AdminGid = 1,
                            AdminGTitle = "非管理員",
                            ActionType = (int)OrderActionType.Pay,
                            ActionTime = tradeTime,
                            ActionDes = "你使用支付寶支付訂單成功,支付寶交易號爲:" + tradeSN
                        });
                    }

                    return RedirectToAction("PaySuccess", "Order", new RouteValueDictionary { { "oid", orderInfo.Oid } });
                }
                else//驗證失敗
                {
                    return new EmptyResult();
                }
            }
            else
            {
                return new EmptyResult();
            }
        }
複製代碼

  第二個方面是通知調用動做方法,代碼以下:


複製代碼
/// <summary>
        /// 通知調用
        /// </summary>
        public ActionResult Notify()
        {
            SortedDictionary<string, string> sPara = AlipayCore.GetRequestPost();

            if (sPara.Count > 0)//判斷是否有帶返回參數
            {
                bool verifyResult = AlipayNotify.Verify(sPara, Request.QueryString["notify_id"], Request.QueryString["sign"], AlipayConfig.SignType, AlipayConfig.Key, AlipayConfig.Code, AlipayConfig.VeryfyUrl, AlipayConfig.Partner);

                if (verifyResult && (Request.QueryString["trade_status"] == "TRADE_FINISHED" || Request.QueryString["trade_status"] == "TRADE_SUCCESS"))//驗證成功
                {
                    int oid = TypeHelper.StringToInt(Request.QueryString["out_trade_no"]);//商戶訂單號
                    string tradeSN = Request.QueryString["trade_no"];//支付寶交易號
                    decimal tradeMoney = TypeHelper.StringToDecimal(Request.QueryString["total_fee"]);//交易金額
                    DateTime tradeTime = TypeHelper.StringToDateTime(Request.QueryString["gmt_payment"]);//交易時間

                    OrderInfo orderInfo = Orders.GetOrderByOid(oid);
                    if (orderInfo.PayMode == 1 && orderInfo.SurplusMoney > 0 && orderInfo.SurplusMoney <= tradeMoney)
                    {
                        Orders.PayOrder(oid, OrderState.Confirming, tradeSN);
                        OrderActions.CreateOrderAction(new OrderActionInfo()
                        {
                            Oid = oid,
                            Uid = orderInfo.Uid,
                            RealName = "本人",
                            AdminGid = 1,
                            AdminGTitle = "非管理員",
                            ActionType = (int)OrderActionType.Pay,
                            ActionTime = tradeTime,
                            ActionDes = "你使用支付寶支付訂單成功,支付寶交易號爲:" + tradeSN
                        });
                    }

                    return new EmptyResult();
                }
                else//驗證失敗
                {
                    return new EmptyResult();
                }
            }
            else
            {
                return new EmptyResult();
            }
        }
複製代碼
/// <summary>
        /// 通知調用
        /// </summary>
        public ActionResult Notify()
        {
            SortedDictionary<string, string> sPara = AlipayCore.GetRequestPost();

            if (sPara.Count > 0)//判斷是否有帶返回參數
            {
                bool verifyResult = AlipayNotify.Verify(sPara, Request.QueryString["notify_id"], Request.QueryString["sign"], AlipayConfig.SignType, AlipayConfig.Key, AlipayConfig.Code, AlipayConfig.VeryfyUrl, AlipayConfig.Partner);

                if (verifyResult && (Request.QueryString["trade_status"] == "TRADE_FINISHED" || Request.QueryString["trade_status"] == "TRADE_SUCCESS"))//驗證成功
                {
                    int oid = TypeHelper.StringToInt(Request.QueryString["out_trade_no"]);//商戶訂單號
                    string tradeSN = Request.QueryString["trade_no"];//支付寶交易號
                    decimal tradeMoney = TypeHelper.StringToDecimal(Request.QueryString["total_fee"]);//交易金額
                    DateTime tradeTime = TypeHelper.StringToDateTime(Request.QueryString["gmt_payment"]);//交易時間

                    OrderInfo orderInfo = Orders.GetOrderByOid(oid);
                    if (orderInfo.PayMode == 1 && orderInfo.SurplusMoney > 0 && orderInfo.SurplusMoney <= tradeMoney)
                    {
                        Orders.PayOrder(oid, OrderState.Confirming, tradeSN);
                        OrderActions.CreateOrderAction(new OrderActionInfo()
                        {
                            Oid = oid,
                            Uid = orderInfo.Uid,
                            RealName = "本人",
                            AdminGid = 1,
                            AdminGTitle = "非管理員",
                            ActionType = (int)OrderActionType.Pay,
                            ActionTime = tradeTime,
                            ActionDes = "你使用支付寶支付訂單成功,支付寶交易號爲:" + tradeSN
                        });
                    }

                    return new EmptyResult();
                }
                else//驗證失敗
                {
                    return new EmptyResult();
                }
            }
            else
            {
                return new EmptyResult();
            }
        }
複製代碼

  第三個方面是咱們須要提供一個支付寶簡介的視圖文件,這個視圖文件在顧客支付訂單時給其展現一些支付寶的說明信息,此文件有如下幾點要求:

  • 文件名必須爲"Show.cshtml"。
  • 此文件必須位於插件項目的Views文件夾的頂層中。
  • 此視圖文件接收類型爲OrderInfo的視圖模型對象。

  這個視圖文件在BrnShop.Web項目的支付展現視圖文件PayShowModel.cshtml中調用,調用方式以下:

@Html.Partial(Model.ShowView, Model.OrderInfo)

  至此支付寶插件開發完成,至於其它類型的插件開發也都是大同小異。

  PS:最後附上一張BrnShop開啓NOSQL先後的性能對比圖,以商品詳細頁面爲例:

    開啓NOSQL前:

  開啓NOSQL後:

  可見性能提高仍是很明顯的。

相關文章
相關標籤/搜索