基於netCore2.1 開發環境下:使用Essensoft.AspNetCore.Payment 實現銀聯app 支付支付寶控件支付接口


一:前言

  由於公司新項目(商城App)要實現銀聯、支付寶、微信等手機端的支付; 發現能使用的.NetCore 支付框架也還不少(跨平台和開源的威力很強大,https://github.com/search?q=alipay),Down了幾個星數較多的來看,最終選用了 Roc 的 Essensoft.AspNetCore.Payment 來實現支付,

github地址為:https://github.com/Essensoft/Payment,目前的最新版本為:V2.30,選用Essensoft.AspNetCore.Payment的原因如下:

1 相對於其它幾個支付應用框架 EssensoftPayment很精簡、構架上類的職責很合理,使用上配置靈活。

2 基於異步的請求實現支付應用框架; 

3 支持.NetCore目前最新版本;

4: 作者的支持力度很強大

基本上保持和支付平台的官方同步更新。並且在1.9X版本時對一起Request進行了重構,在使用過程中發現的一些小問題或合理建議,反饋給作者,作者都用抽空快速的解決了,這要比選用幾年都不更新的框架好吧。

特別是像微信與銀聯之類的支付平台,支付接口變動是很正常的。比如說阿里支付2018年新申請的商戶停用Md5使用RSA

5 支持國內的多種支付渠道:目前支持:支付寶(Alipay)、微信支付(WeChatPay)、QQ錢包(QPay)、京東支付(JDPay)、連連支付(LianLianPay)、銀聯支付(UnionPay)

 

二:如何用使用 Essensoft/Payment

2.1 Essensoft/Payment的下載與配置

首先建立一個基於netCore的Web項目,通過Nuget里查詢Essensoft/Payment 並下載最新的版本;說明下:

Essensoft.AspNetCore.Payment.Security:用於幾種支付接口里的加密解決等 (必須引用到項目中)

 由於命名規則是基於Essensoft.AspNetCore.Payment 起頭的,Essensoft.AspNetCore.Payment.UnionPay表示銀聯的支付,在使用過程中我們根據自己的需要引入相關的Nuget包

我這里引入了Essensoft.AspNetCore.Payment.UnionPay、Essensoft.AspNetCore.Payment.Alipay、Essensoft.AspNetCore.Payment.WeChatPay及Essensoft.AspNetCore.Payment.Security

2.2  建立銀聯支付控制器可以是Web 控制器,也可以是WebApi的控制器,我使用的類名為:UnionPayController

2.3 配置銀聯支付參數說明

Essensoft.AspNetCore.Payment 支持 構造函數方式和配置選項方式配置:

本文以:Option的方式在appsettings.json中配置:內容如下:

"UnionPay": {
"MerId": "8000000000001",
"AccessType": "0",
"Version": "5.1.0",
"Encoding": "UTF-8",
"SignMethod": "01",
"SignCert": "Testcert/mycret1.pfx",
"SignCertPassword": "112233",
"EncryptCert": "Testcert/acp_prod_enc.cer",
"MiddleCert": "Testcert/acp_prod_middle.cer",
"RootCert": "Testcert/acp_prod_root.cer",
"SecureKey": "112233",
"TestMode": "true"
},

"Alipay": {
"AppId": "201811XXXXXXXXXX",
"EncyptKey": "lf/XXXXXXXXXXX",
"RsaPublicKey": "MiXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"RsaPrivateKey": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
},

以上配置是測試模式的配置:銀聯相關的證書文件在官方DEMO有提供下載:測試賬號登錄地址:open.unionpay.com 

生產賬號登錄地址:https://merchant.unionpay.com/

需要注意的時:在使用支付寶RSA驗簽工具時:生成的商戶使用私鑰和商戶應用公鑰要保存好,需要到銀聯平台上去通過“商戶應用公鑰”生成支付寶公鑰,

即生成我們配置參數中的。RsaPublicKey,而RsaPrivateKey則是我們用支付寶RSA驗簽生成 商戶私鑰

 以下是支付寶控制器的代碼:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using BusinessServer.Order;
using Essensoft.AspNetCore.Payment.Alipay;
using Essensoft.AspNetCore.Payment.Alipay.Domain;
using Essensoft.AspNetCore.Payment.Alipay.Notify;
using Essensoft.AspNetCore.Payment.Alipay.Request;
using log4net;
using Microsoft.AspNetCore.Mvc;
using MobileWebApi.Base;
using MobileWebApi.Base.dto;
using MobileWebApi.Base.tools;


namespace PaymentGateWay
{
public class AliPayController : Controller
{
private readonly IAlipayClient _client;
private readonly IAlipayNotifyClient _notifyClient;
private IOrderServer _orderServer;
private ILog log; //Log4組件

public AliPayController(IAlipayClient client, IAlipayNotifyClient notifyClient, IOrderServer orderServer)
{
_orderServer = orderServer;
_client = client;
_notifyClient = notifyClient;
this.log = LogManager.GetLogger(Startup.repository.Name, typeof(UnionPayController));
}

 

/// <summary>
/// 發起支付請求:由ApiColud調用
/// </summary>
/// <param name="dto">手機端傳過來的Dto包括訂單編號,用戶ID,token信息</param>
/// <returns></returns>
[HttpPost] //[FromBody]OrderPayDto dto

public async Task<HttpResponseMessage> AppPay(OrderPayDto dto)
{
var result = new APITipResult();//返回對象
string Msg = "";
var order = _orderServer.GetModel(new DoMain.Request.Order.OrderInfoRequest() { order_id = dto.OrderId });
var orderState = OrderCheckTools.CheckOrderState(dto, order, out Msg);//檢查訂單是否可以支付
if (!string.IsNullOrWhiteSpace(Msg) && !orderState) //如果orderState=false 並且出錯消息不為空時提示客戶端不能支付
{
result.message = Msg;
result.code = 1;
order = null;
return WebApiHelper.ToJson(result);
}
decimal payMoney = order.order_price * 100; //支付金額:按分來計算
var model = new AlipayTradeAppPayModel()
{
OutTradeNo = dto.OrderId,
Subject = dto.OrderId + "訂單支付",
ProductCode = "QUICK_MSECURITY_PAY",
TotalAmount = order.order_price.ToString(),
Body = "XXXX訂單支付",
};
var req = new AlipayTradeAppPayRequest();
req.SetBizModel(model);
req.SetNotifyUrl("http://Engine1024.nat123.net/AliPay/AsynNotify");
req.SetReturnUrl("http://Engine1024.nat123.net/AliPay/AsynNotify");
var response = await _client.SdkExecuteAsync(req);
result.data = response.Body;
return WebApiHelper.ToJson(result);
}


/// <summary>
/// 支付回調
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<IActionResult> AsynNotify()
{
try
{
var notify = await _notifyClient.ExecuteAsync<AlipayTradeAppPayNotify>(Request);
string json = Newtonsoft.Json.JsonConvert.SerializeObject(notify, Newtonsoft.Json.Formatting.Indented);
log.Info("Resp=" + json);
decimal order_price = decimal.Parse(notify.BuyerPayAmount);
string out_trade_no = notify.OutTradeNo; //商戶訂單
string trade_status = notify.TradeStatus; // "支付狀態"
string trade_no = notify.TradeNo; // 支付寶交易號
if (notify.TradeStatus == "TRADE_SUCCESS")
{
 //這里寫支付成功的業務邏輯
}
else
{
 //這里寫支付失敗的業務處理
}
 
}
catch(SystemException ex)
{
string json = Newtonsoft.Json.JsonConvert.SerializeObject(ex, Newtonsoft.Json.Formatting.Indented);
log.Error("Errors=" + json);
}
return null;
}

}
}

 

 以下銀聯支付的源碼

using System.Collections.Generic;
using System.Collections.Specialized;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using BusinessServer.Order;
using DoMain.Entity.Order;
using Essensoft.AspNetCore.Payment.UnionPay;
using Essensoft.AspNetCore.Payment.UnionPay.Notify;
using Essensoft.AspNetCore.Payment.UnionPay.Request;
using Essensoft.AspNetCore.Payment.UnionPay.Response;
using log4net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using MobileWebApi.Base;
using MobileWebApi.Base.dto;
using MobileWebApi.Base.tools;

namespace PaymentGateWay
{
public class UnionPayController : Controller
{
private readonly IUnionPayClient _client;
private readonly IUnionPayNotifyClient _notifyClient;
private IOrderServer _orderServer;
private ILog log;


public UnionPayController(IUnionPayClient client, IUnionPayNotifyClient notifyClient, IOrderServer orderServer)
{
_orderServer = orderServer;
_client = client;
_notifyClient = notifyClient;
this.log = LogManager.GetLogger(Startup.repository.Name, typeof(UnionPayController));
}

/// <summary>
/// 支付 [FromBody]OrderPayDto dto
/// </summary>
/// <param name="viewModel"></param>
/// <returns></returns>
[HttpPost]
public async Task<HttpResponseMessage> AppPay(OrderPayDto dto)
{
var result = new APITipResult();
string Msg = "";
try
{
var order = _orderServer.GetModel(new DoMain.Request.Order.OrderInfoRequest() { order_id = dto.OrderId });
var orderState = OrderCheckTools.CheckOrderState(dto, order, out Msg);
if (Msg != "" && !orderState)
{
result.message = Msg;
result.code = 1;
order = null;
return WebApiHelper.ToJson(result);
}
decimal payMoney =order.order_price*100;//支付金額
var request = new UnionPayMobileControlPayConsumeRequest
{
TxnType = "01",
TxnSubType = "01",
BizType = "000201",
ChannelType = "08",
OrderId = dto.OrderId,
TxnTime = System.DateTime.Now.ToString("yyyyMMddhhmmss"),
TxnAmt = ((double)(payMoney)).ToString(),
CurrencyCode = "156",
FrontUrl = "http://Engine1024.nat123.net/Payment/Unionpay/AsynNotify",
BackUrl = "http://Engine1024.nat123.net/Payment/Unionpay/AsynNotify"
};
var response = await _client.ExecuteAsync(request);
if (response.RespCode == "00" && response.Tn != "")
{
result.data = response.Tn;
}
else
{
result.data = "";
}
return WebApiHelper.ToJson(result);
}
catch (System.Exception ex)
{
string json = Newtonsoft.Json.JsonConvert.SerializeObject(ex, Newtonsoft.Json.Formatting.Indented);
log.Error("Error:" + json);
return WebApiHelper.ToJson(result);
}
}

 

/// <summary>
/// 網關頁面支付 - 同步跳轉 6226090000000048
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<IActionResult> AsynNotify()
{
try
{
var notify = await _notifyClient.ExecuteAsync<UnionPayMobileControlPayConsumeNotify>(Request);
string json = Newtonsoft.Json.JsonConvert.SerializeObject(notify, Newtonsoft.Json.Formatting.Indented);
decimal order_price = decimal.Parse(notify.TxnAmt)/100;
log.Info("order_price==" + order_price + " pay RespCode " + notify.RespCode + " queryId =" + notify.QueryId + " orderId =" + notify.OrderId + " txnAmt=" + notify.TxnAmt);
if (notify.RespCode== "00")
{
 //成付成功
}
else
{
//成付失敗

}

ViewData["response"] = "支付成功";
return View();
}
catch(System.Exception ex)
{
string json = Newtonsoft.Json.JsonConvert.SerializeObject(ex, Newtonsoft.Json.Formatting.Indented);
ViewData["response"] = "出現錯誤";
return View();
}
}

}
 

}

 

 

setup.cs配置:

public class Startup
{
public static ILoggerRepository repository { get; set; }

public Startup(IConfiguration configuration)
{
Configuration = configuration;
repository = LogManager.CreateRepository("NETCoreRepository");
XmlConfigurator.Configure(repository, new FileInfo("log4net.config"));
}

public IConfiguration Configuration { get; }

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});

services.AddSingleton<IConfiguration>(Configuration);
services.AddTransient<IDapper, DapperBase>();
services.AddTransient<IOrderServer, OrderServer>();
services.AddTransient<IOrderOrderRepository<OrderInfo>, OrderOrderRepository>();
services.AddRouting();
// 引入HttpClient
services.AddHttpClient();
// 引入Payment 依賴注入
services.AddAlipay();
services.AddUnionPay();
services.AddWeChatPay();
// 在 appsettings.json 中 配置選項
services.Configure<AlipayOptions>(Configuration.GetSection("Alipay"));
services.Configure<UnionPayOptions>(Configuration.GetSection("UnionPay"));
services.Configure<WeChatPayOptions>(Configuration.GetSection("WeChatPay"));
services.AddWebEncoders(opt =>
{
opt.TextEncoderSettings = new TextEncoderSettings(UnicodeRanges.All);
});

services.AddMvc(o => o.InputFormatters.Insert(0, new HandleRequestBodyFormatter())).AddWebApiConventions().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
//AddWebApiConventions :返回HttpResponseMessage時:需要安裝 nuget 包 Microsoft.AspNetCore.Mvc.WebApiCompatShim
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env )
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");

});
}
}
}

 

 

 

 

 

 

 

 

 

 

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM