# PaymentService.Prepayment

ABP version (opens new window) NuGet (opens new window) NuGet Download (opens new window) Discord online (opens new window) GitHub stars (opens new window)

Prepayment implementation of the EasyAbp.PaymentService module.

# Online Demo

We have launched an online demo for this module: https://pay.samples.easyabp.io (opens new window)

# Installation

Should also install the PaymentService module since this module depends on it.

  1. Install the following NuGet packages. (see how (opens new window))

    • EasyAbp.PaymentService.Prepayment.Application
    • EasyAbp.PaymentService.Prepayment.Application.Contracts
    • EasyAbp.PaymentService.Prepayment.Domain
    • EasyAbp.PaymentService.Prepayment.Domain.Shared
    • EasyAbp.PaymentService.Prepayment.EntityFrameworkCore
    • EasyAbp.PaymentService.Prepayment.HttpApi
    • EasyAbp.PaymentService.Prepayment.HttpApi.Client
    • (Optional) EasyAbp.PaymentService.Prepayment.MongoDB
    • (Optional) EasyAbp.PaymentService.Prepayment.Web
  2. Add DependsOn(typeof(PaymentServicePrepaymentXxxModule)) attribute to configure the module dependencies. (see how (opens new window))

  3. Add builder.ConfigurePaymentServicePrepayment(); to the OnModelCreating() method in MyProjectMigrationsDbContext.cs.

  4. Add EF Core migrations and update your database. See: ABP document (opens new window).

# Usage

  1. Register the Prepayment payment method:

    Configure<PaymentServiceOptions>(options =>
    {
        options.Providers.Configure<PrepaymentPaymentServiceProvider>(PrepaymentPaymentServiceProvider.PaymentMethod);
    });
    
  2. Configure the prepayment to define a account group:

    Configure<PaymentServicePrepaymentOptions>(options =>
    {
        options.AccountGroups.Configure<DefaultAccountGroup>(accountGroup =>
        {
            accountGroup.Currency = "CNY";
        });
    });
    

    please refer to the ConfigurePaymentServicePrepayment method in the Web module (opens new window) of the sample app.

  3. Access the API /api/paymentService/prepayment/account (with the request param UserId), then the account will be created automatically.

  4. Top up your account:

    1. Use the API /api/paymentService/prepayment/account/topUp to start top-up.

    2. Use the API /api/paymentService/prepayment/account/{id} to get the ExtraProperties.PendingTopUpPaymentId.

    3. Use the API /api/paymentService/payment/{id}/pay to finish the payment. (for example you can use WeChatPay to top up your prepayment account, please refer to the document of the payment method you want)

    4. If you want to cancel an ongoing payment, please use the API /api/paymentService/payment/{id}/cancel.

    Or just change the balance directly with the management pages if you have the account management permission.

  5. Pay with prepayment account.

    1. Users can use the API /api/paymentService/payment/{id}/pay to finish the payment, please put the necessary params in the ExtraProperties:

      {
          "extraProperties": {
              "AccountId": "82D49C17-9282-4822-9EE9-A0685529D707" // Id of the prepayment account that you use to pay
          }
      }
      

    Skip the following steps if you are using the EasyAbp.EShop (opens new window).

    See more steps
    1. Create a payment with the payment method Prepayment.

      Other modules or apps that depend on PaymentService module should create payments via distributed events.

      See sample code
      await _distributedEventBus.PublishAsync(new CreatePaymentEto
      {
          TenantId = CurrentTenant.Id,
          UserId = CurrentUser.GetId(),
          PaymentMethod = "Prepayment",   // Should specify the payment method as "Prepayment"
          Currency = "CNY",   // Should be same as the currency configuration of your prepayment account group
          PaymentItems = orders.Select(order => new CreatePaymentItemEto
          {
              ItemType = "MyCustomKeyword", // It is just a sample and you can customize it yourself
              ItemKey = order.Id,
              OriginalPaymentAmount = order.Price
          }).ToList()
      });
      

      please refer to the usage in EShop (opens new window)

    2. Handle the payment created distributed event to get and remember the PaymentId.

      See sample code

      public class MyCustomPaymentCreatedEventHandler : IDistributedEventHandler<EntityCreatedEto<PaymentEto>>, ITransientDependency
      {
          [UnitOfWork(isTransactional: true)]
          public virtual async Task HandleEventAsync(EntityCreatedEto<PaymentEto> eventData)
          {
              foreach (var item in eventData.Entity.PaymentItems.Where(item => item.ItemType == "MyCustomKeyword"))
              {
                  // Persistence the PaymentId of the ongoing payment, so user can get it in some way.
              }
          }
      }
      

      please refer to the usage in EShop (opens new window)

    3. Handle the payment canceled distributed event to clear the remembered the PaymentId.

      See sample code

      public class MyCustomPaymentCanceledEventHandler : IDistributedEventHandler<PaymentCanceledEto>, ITransientDependency
      {
          [UnitOfWork(isTransactional: true)]
          public virtual async Task HandleEventAsync(PaymentCanceledEto payment)
          {
              foreach (var item in payment.PaymentItems.Where(item => item.ItemType == "MyCustomKeyword"))
              {
                  // Remove the remembered PaymentId.
              }
          }
      }
      

      please refer to the usage in EShop (opens new window)

    4. Handle the payment completed distributed event:

      See sample code

      public class MyCustomPaymentCompletedEventHandler : IDistributedEventHandler<PaymentCompletedEto>, ITransientDependency
      {
          [UnitOfWork(isTransactional: true)]
          public virtual async Task HandleEventAsync(PaymentCompletedEto payment)
          {
              foreach (var item in payment.PaymentItems.Where(item => item.ItemType == "MyCustomKeyword"))
              {
                  // Maybe you can automatically send out the goods to the customer here.
              }
          }
      }
      

      please refer to the usage in EShop (opens new window)

# Roadmap

  • [ ] Unit tests.
Last Updated: 8/26/2022, 9:14:33 AM