nopCommerce 3.9 大波浪系列 之 可退款的支付宝插件(下)

Posted 大波浪 要上进

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了nopCommerce 3.9 大波浪系列 之 可退款的支付宝插件(下)相关的知识,希望对你有一定的参考价值。

一.回顾

支付宝插件源码下载地址:点击下载      

    上篇介绍了使用支付宝插件进行支付,全额退款,部分退款还有插件的多店铺配置,本文介绍下如何实现的。

二.前期准备

    插件主要有3个功能:

  1. 多店铺插件配置 
  2. 支付功能
  3. 退款功能

   数据库支持:

  1. 新增dbl_PaymentInfo表保存支付记录。
  2. 新增dbl_RefundInfo表保存退款记录。

   其他准备:

  1. 支付宝即时到账PID和MD5秘钥Key,可通过支付宝开放平台获取。

三.流程规划 

  1. 插件安装卸载流程

FX]3{CKOJX5`(@G}_MUO6(D

   2.  支付流程

98UDRBDZ2Q_[`8O@%ZIZU_M

   3.  退款流程

{EM~~HSKQWNTTT$438(CJJ5

四.创建项目

    1.  新建类库项目,名称为 DaBoLang.Nop.Plugin.Payments.AliPay,位置放在Plugins下

image_thumb2

    2.  点击项目快捷键Alt+Enter进入项目属性,

         设置输出路径为..\\..\\Presentation\\Nop.Web\\Plugins\\DaBoLang.Payments.AliPay\\

image_thumb4

    3.  安装相关包:项目根目录新建packages.config文件,内容如下

  1 <?xml version="1.0" encoding="utf-8"?>
  2 <packages>
  3   <package id="Autofac" version="4.4.0" targetFramework="net451" />
  4   <package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net451" />
  5   <package id="Microsoft.AspNet.Razor" version="3.2.3" targetFramework="net451" />
  6   <package id="Microsoft.AspNet.WebPages" version="3.2.3" targetFramework="net451" />
  7   <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net451" />
  8 </packages>

      打开【工具】【NuGet 包管理器】【程序包管理器控制台】,

      输入下边命令更新包: Update-Package -ProjectName \'DaBoLang.Nop.Plugin.Payments.AliPay\'  -Reinstall

image_thumb6

      最后添加 Nop.Core  Nop.Data   Nop.Services  Nop.Web.FrameWork 项目引用

    4.  创建插件描述文件:根目录新建Description.txt文件 用于插件描述,写入内容如下:

  1 Group: Payment methods
  2 FriendlyName: 支付宝
  3 SystemName: DaBoLang.Payments.AliPay
  4 Version: 1.00
  5 SupportedVersions: 3.90
  6 Author: 大波浪
  7 DisplayOrder: 1
  8 FileName: DaBoLang.Nop.Plugin.Payments.AliPay.dll
  9 Description: 支付宝 即时到账 插件,支持支付,退款

    5. 创建项目目录,如果你已经下载了插件项目参考项目目录如下:

image_thumb[1]

  • Alipay  支付宝即时到账相关
  • Controllers 控制器文件夹
  • Data    数据库相关
  • Domain 实体类
  • Models  模型
  • Services  服务接口
  • Views  视图
  • AliPayPaymentProcessor.cs   支付插件实现类
  • AliPayPaymentSettings.cs     支付宝即时到账配置类
  • DependencyRegistrar.cs     依赖注入扩展类
  • Description.txt   插件描述文件
  • RouteProvider.cs    路由注册类

五.创建数据库

     项目我们已经创建好了。记下来我们创建付款记录表和退款记录表用于保存相关记录。nop使用的是ORM框架为Entity Framework框架,我们使用Code First模式来创建。

image

    1.  在Domain文件夹创建imagePaymentInfo类用于保存付款信息,RefundInfo类用于保存退款信息。

nop中的实体类需要继承 Nop.Core.BaseEntity 抽象方法。

  1 using Nop.Core;
  2 using Nop.Core.Domain.Customers;
  3 using Nop.Core.Domain.Orders;
  4 using System;
  5 using System.Collections.Generic;
  6 using System.Diagnostics;
  7 using System.Globalization;
  8 using System.Linq;
  9 
 10 namespace DaBoLang.Nop.Plugin.Payments.AliPay.Domain
 11 {
 12     /// <summary>
 13     /// 命名空间:DaBoLang.Nop.Plugin.Payments.AliPay.Domain
 14     /// 名    称:PaymentInfo
 15     /// 功    能:实体类
 16     /// 详    细:付款记录
 17     /// 版    本:1.0.0.0 
 18     /// 作    者:大波浪
 19     /// 联系方式:http://www.cnblogs.com/yaoshangjin
 20     /// 说    明:
 21     /// </summary>
 22     public partial class PaymentInfo : BaseEntity
 23     {
 24         #region Properties
 25         public Guid PaymentGuid { get; set; }
 26         /// <summary>
 27         /// 订单编号
 28         /// </summary>
 29         public int OrderId { get; set; }
 30         /// <summary>
 31         /// 插件SystemName
 32         /// </summary>
 33         public string Name { get; set; }
 34         /// <summary>
 35         /// 交易金额
 36         /// </summary>
 37         public decimal Total { get; set; }
 38         /// <summary>
 39         /// 订单编号外部交易号
 40         /// </summary>
 41         public string Out_Trade_No { get; set; }
 42         /// <summary>
 43         /// 说明
 44         /// </summary>
 45         public string Note { get; set; }
 46         /// <summary>
 47         /// 交易号,内部交易号,支付宝交易号或者微信交易号
 48         /// </summary>
 49         public string Trade_no { get; set; }
 50         /// <summary>
 51         /// 第三方交易状态
 52         /// </summary>
 53         public string Trade_status { get; set; }
 54         /// <summary>
 55         /// 收款单位email
 56         /// </summary>
 57         public string Seller_email { get; set; }
 58         /// <summary>
 59         /// 收款单位id
 60         /// </summary>
 61         public string Seller_id { get; set; }
 62         /// <summary>
 63         /// 付款账户id
 64         /// </summary>
 65         public string Buyer_id { get; set; }
 66         /// <summary>
 67         /// 付款账户email
 68         /// </summary>
 69         public string Buyer_email { get; set; }
 70        /// <summary>
 71        /// 内部订单创建时间
 72        /// </summary>
 73         public DateTime CreateDateUtc { get; set; }
 74 
 75         #endregion
 76     }
 77 }
 78 
PaymentInfo
  1 using Nop.Core;
  2 using Nop.Core.Domain.Customers;
  3 using Nop.Core.Domain.Orders;
  4 using System;
  5 using System.Collections.Generic;
  6 using System.Diagnostics;
  7 using System.Globalization;
  8 using System.Linq;
  9 
 10 namespace DaBoLang.Nop.Plugin.Payments.AliPay.Domain
 11 {
 12     /// <summary>
 13     /// 命名空间:DaBoLang.Nop.Plugin.Payments.AliPay.Domain
 14     /// 名    称:RefundInfo
 15     /// 功    能:实体类
 16     /// 详    细:退款记录
 17     /// 版    本:1.0.0.0
 18     /// 作    者:大波浪
 19     /// 联系方式:http://www.cnblogs.com/yaoshangjin
 20     /// 说    明:
 21     /// </summary>
 22     public partial class RefundInfo : BaseEntity
 23     {
 24 
 25         #region Properties
 26         public int OrderId { get; set; }
 27         /// <summary>
 28         /// 退款状态
 29         /// </summary>
 30         public int RefundStatusId { get; set; }
 31         /// <summary>
 32         /// 退款金额
 33         /// </summary>
 34         public decimal AmountToRefund { get; set; }
 35         public string Seller_Email { get; set; }
 36         public string Seller_Id { get; set; }
 37         /// <summary>
 38         /// 交易号,内部交易号,支付宝交易号或者微信交易号
 39         /// </summary>
 40         public string Batch_no { get; set; }
 41         /// <summary>
 42         /// 订单标号外部交易号
 43         /// </summary>
 44         public string Out_Trade_No { get; set; }
 45         /// <summary>
 46         /// 创建时间
 47         /// </summary>
 48         public DateTime CreateOnUtc { get; set; }
 49         /// <summary>
 50         /// 退款成功时间
 51         /// </summary>
 52         public DateTime? RefundOnUtc { get; set; }
 53 
 54         /// <summary>
 55         /// 回调ID
 56         /// </summary>
 57         public string Notify_Id { get; set; }
 58         /// <summary>
 59         /// 回调类型
 60         /// </summary>
 61         public string Notify_Type { get; set; }
 62 
 63         public string Result_Details { get; set; }
 64         #endregion
 65 
 66         /// <summary>
 67         /// 订单状态
 68         /// </summary>
 69         public RefundStatus RefundStatus
 70         {
 71             get
 72             {
 73                 return (RefundStatus)this.RefundStatusId;
 74             }
 75             set
 76             {
 77                 this.RefundStatusId = (int)value;
 78             }
 79         }
 80 
 81     }
 82     public enum RefundStatus
 83     {
 84         /// <summary>
 85         /// 申请退款
 86         /// </summary>
 87         refunding = 10,
 88         /// <summary>
 89         /// 退款成功
 90         /// </summary>
 91         refund = 20,
 92         /// <summary>
 93         /// 取消退款
 94         /// </summary>
 95         cancel = 30,
 96         /// <summary>
 97         /// 退款过期
 98         /// </summary>
 99         overtime = 40,
100         /// <summary>
101         /// 退款失败
102         /// </summary>
103         error = 50,
104     }
105 }
106 
RefundInfo

    2.  Data文件夹中创建实体与数据库的映射关系配置

image

nop中映射关系配置需要继承  Nop.Data.Mapping.NopEntityTypeConfiguration<T> 接口,T泛型为映射的实体类 

该接口也是继承EntityTypeConfiguration<T>接口的    

    PaymentInfoMap类关联PaymentInfo实体类,

    构造函数中通过this.ToTable("dbl_PaymentInfo")指定数据库表明,this.HasKey(x => x.Id);指定主键

  1 using DaBoLang.Nop.Plugin.Payments.AliPay.Domain;
  2 using Nop.Data.Mapping;
  3 
  4 namespace DaBoLang.Nop.Plugin.Payments.AliPay.Data
  5 {
  6     /// <summary>
  7     /// 命名空间:DaBoLang.Nop.Plugin.Payments.AliPay.Data
  8     /// 名    称:PaymentInfoMap
  9     /// 功    能:实体映射
 10     /// 详    细:支付表映射
 11     /// 作    者:大波浪
 12     /// </summary>
 13     public partial class PaymentInfoMap : NopEntityTypeConfiguration<PaymentInfo>
 14     {
 15         public PaymentInfoMap()
 16         {
 17             this.ToTable("dbl_PaymentInfo");
 18             this.HasKey(x => x.Id);
 19         }
 20     }
 21 }

      RefundInfoMap则将RefundInfo实体类与dbl_RefundInfo表进行关联。

      this.Ignore(x=>x.RefundStatus); 表示忽略RefundStatus属性,忽略的属性在创建数据时不会创建该属性字段。

  1 using DaBoLang.Nop.Plugin.Payments.AliPay.Domain;
  2 using Nop.Data.Mapping;
  3 
  4 namespace DaBoLang.Nop.Plugin.Payments.AliPay.Data
  5 {
  6     /// <summary>
  7     /// 命名空间:DaBoLang.Nop.Plugin.Payments.AliPay.Data
  8     /// 名    称:RefundInfoMap
  9     /// 功    能:实体映射
 10     /// 详    细:退款记录映射
 11     /// </summary>
 12     public partial class RefundInfoMap : NopEntityTypeConfiguration<RefundInfo>
 13     {
 14         public RefundInfoMap()
 15         {
 16             this.ToTable("dbl_RefundInfo");
 17             this.HasKey(x => x.Id);
 18             this.Ignore(x=>x.RefundStatus);
 19         }
 20     }
 21 }

   3.  创建数据库上下文

       我们已经创建好2个表的实体类和映射关系,接下来我们需要创建DbContext数据库上下文。

       在Data目录下创建 AliPayObjectContext类,继承DbContext类和Nop.Data.IDbContext接口

重写OnModelCreating方法,将Map配置添加到EF中,

提示:Nop.Data.NopObjectContext是Nop默认上下文可供,这里也可以使用反射机制自动添加配置,当然需要再提取一次Map接口,有兴趣的朋友自行扩展。

  1  protected override void OnModelCreating(DbModelBuilder modelBuilder)
  2         {
  3             modelBuilder.Configurations.Add(new PaymentInfoMap());
  4             modelBuilder.Configurations.Add(new RefundInfoMap());
  5 
  6             //disable EdmMetadata generation
  7             //modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
  8             base.OnModelCreating(modelBuilder);
  9         }

添加Install()方法创建表,Uninstall()方法删除表。

  1        /// <summary>
  2         /// 安装
  3         /// </summary>
  4         public void Install()
  5         {
  6             //创建表
  7             var dbScript = CreateDatabaseScript();
  8             Database.ExecuteSqlCommand(dbScript);
  9             SaveChanges();
 10         }
 11 
 12         /// <summary>
 13         /// 卸载
 14         /// </summary>
 15         public void Uninstall()
 16         {
 17             //删除表
 18             var tableName = this.GetTableName<PaymentInfo>();
 19             this.DropPluginTable(tableName);
 20             tableName = this.GetTableName<RefundInfo>();
 21             this.DropPluginTable(tableName);
 22         }

完整的代码如下

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Data.Entity;
  4 using System.Data.Entity.Infrastructure;
  5 using Nop.Core;
  6 using Nop.Data;
  7 using DaBoLang.Nop.Plugin.Payments.AliPay.Domain;
  8 
  9 namespace DaBoLang.Nop.Plugin.Payments.AliPay.Data
 10 {
 11     /// <summary>
 12     /// 命名空间:DaBoLang.Nop.Plugin.Payments.AliPay.Data
 13     /// 名    称:AliPayObjectContext
 14     /// 功    能:数据库
 15     /// 详    细:数据库上下文
 16     /// 版    本:1.0.0.0
 17     /// 文件名称:AliPayObjectContext.cs
 18     /// 作    者:大波浪
 19     /// 联系方式:http://www.cnblogs.com/yaoshangjin
 20     /// 说    明:
 21     /// </summary>
 22     public class AliPayObjectContext : DbContext, IDbContext
 23     {
 24         #region Ctor
 25 
 26         public AliPayObjectContext(string nameOrConnectionString)
 27             : base(nameOrConnectionString)
 28         {
 29             //((IObjectContextAdapter) this).ObjectContext.ContextOptions.LazyLoadingEnabled = true;
 30         }
 31 
 32         #endregion
 33 
 34         #region Utilities
 35 
 36         protected override void OnModelCreating(DbModelBuilder modelBuilder)
 37         {
 38             modelBuilder.Configurations.Add(new PaymentInfoMap());
 39             modelBuilder.Configurations.Add(new RefundInfoMap());
 40 
 41             //disable EdmMetadata generation
 42             //modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
 43             base.OnModelCreating(modelBuilder);
 44         }
 45 
 46         #endregion
 47 
 48         #region Methods
 49 
 50         public string CreateDatabaseScript()
 51         {
 52             return ((IObjectContextAdapter)this).ObjectContext.CreateDatabaseScript();
 53         }
 54 
 55         public new IDbSet<TEntity> Set<TEntity>() where TEntity : BaseEntity
 56         {
 57             return base.Set<TEntity>();
 58         }
 59 
 60         /// <summary>
 61         /// 安装
 62         /// </summary>
 63         public void Install()
 64         {
 65             //create the table
 66             var dbScript = CreateDatabaseScript();
 67             Database.ExecuteSqlCommand(dbScript);
 68             SaveChanges();
 69         }
 70 
 71         /// <summary>
 72         /// 卸载
 73         /// </summary>
 74         public void Uninstall()
 75         {
 76             //删除表
 77             var tableName = this.GetTableName<PaymentInfo>();
 78             this.DropPluginTable(tableName);
 79             tableName = this.GetTableName<RefundInfo>();
 80             this.DropPluginTable(tableName);
 81         }
 82 
 83         /// <summary>
 84         /// Execute stores procedure and load a list of entities at the end
 85         /// </summary>
 86         /// <typeparam name="TEntity">Entity type</typeparam>
 87         /// <param name="commandText">Command text</param>
 88         /// <param name="parameters">Parameters</param>
 89         /// <returns>Entities</returns>
 90         public IList<TEntity> ExecuteStoredProcedureList<TEntity>(string commandText, params object[] parameters) where TEntity : BaseEntity, new()
 91         {
 92             throw new NotImplementedException();
 93         }
 94 
 95         /// <summary>
 96         /// Creates a raw SQL query that will return elements of the given generic type.  The type can be any type that has properties that match the names of the columns returned from the query, or can be a simple primitive type. The type does not have to be an entity type. The results of this query are never tracked by the context even if the type of object returned is an entity type.
 97         /// </summary>
 98         /// <typeparam name="TElement">The type of object returned by the query.</typeparam>
 99         /// <param name="sql">The SQL query string.</param>
100         /// <param name="parameters">The parameters to apply to the SQL query string.</param>
101         /// <returns>Result</returns>
102         public IEnumerable<TElement> SqlQuery<TElement>(string sql, params object[] parameters)
103         {
104             throw new NotImplementedException();
105         }
106 
107         /// <summary>
108         /// Executes the given DDL/DML command against the database.
109         /// </summary>
110         /// <param name="sql">The command string</param>
111         /// <param name="doNotEnsureTransaction">false - the transaction creation is not ensured; true - the transaction creation is ensured.</param>
112         /// <param name="timeout">Timeout value, in seconds. A null value indicates that the default value of the underlying provider will be used</param>
113         /// <param name="parameters">The parameters to apply to the command string.</param>
114         /// <returns>The result returned by the database after executing the command.</returns>
115         public int ExecuteSqlCommand(string sql, bool doNotEnsureTransaction = false, int? timeout = null, params object[] parameters)
116         {
117             throw new NotImplementedException();
118         }
119 
120         /// <summary>
121         /// Detach an entity
122         /// </summary>
123         /// <param name="entity">Entity

以上是关于nopCommerce 3.9 大波浪系列 之 可退款的支付宝插件(下)的主要内容,如果未能解决你的问题,请参考以下文章

nopCommerce 3.9 大波浪系列 之 开发支持多店的插件

nopCommerce 3.9 大波浪系列 之 引擎 NopEngine

nopCommerce 3.9 大波浪系列 之 汉化-中文语言

nopCommerce 3.9 大波浪系列 之 汉化-Roxy Fileman

nopCommerce 3.9 大波浪系列 之 global.asax

nopCommerce 3.9 大波浪系列 之 路由扩展 [多语言Seo的实现]