ASP.NET Core2.0 環境下MVC模式的支付寶PC網站支付接口-沙箱環境開發測試

1.新建.NET Core web項目

2.Controllers-Models-Views 分三個大部分

3.下載安裝最新sdk

官方的SDK以及Demo都還是.NET Framework的,根據官方文檔說明新建網站后還是需要引用官方SDK的源碼,

在這里直接使用網上一位朋友的用.NET Standard 2.0 進行實現了支付寶服務端SDK,Alipay.AopSdk.Core(github:https://github.com/stulzq/Alipay.AopSdk.Core) ,支持.NET CORE 2.0。

為了使用方便以直接使用Nuget下載安裝,直接使用集成的SDK即可,道理和官網支付寶demo一個樣。

通過Nuget安裝:Install-Package Alipay.AopSdk.Core

4.首先要配置支付寶商戶信息 在這里使用的是沙箱賬號

新建一個配置類基本不用但是后續代碼還是可以方便使用。

Config.cs

using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;namespace Alipay.PCPayment
{public class Config{// 應用ID,您的APPID 沙箱public static string AppId= "2016********3";/// <summary>/// 合作商戶uid 沙箱/// </summary>public static string Uid= "208**********2";// 支付寶網關 沙箱地址public static string Gatewayurl="https://openapi.alipaydev.com/gateway.do";// 支付寶網關 生產地址// public static string Gatewayurl = "https://openapi.alipay.com/gateway.do";/// <summary>/// 異步通知 處理支付寶接口通知返回 獲取是否是支付寶服務器發來的請求的驗證結果/// </summary>/// <param name="notifyId">通知驗證ID</param>/// <returns>驗證結果</returns>public static async Task<string> VerifyNotifyAsync(string notifyId){return await SendAsync(Uid, notifyId);}/// <summary>///  //支付寶消息驗證地址/// </summary>private const string API_URL = "https://mapi.alipay.com/gateway.do?service=notify_verify&";/// <summary>/// 獲取是否是支付寶服務器發來的請求的驗證結果/// </summary>/// <param name="partner">partner 合作身份ID</param>/// <param name="notify_id">通知驗證ID</param>/// <returns>驗證結果</returns>public static async Task<string> SendAsync(string partner, string notify_id){string strResult;string verifyUrl = API_URL + "partner=" + partner + "&notify_id=" + notify_id;//獲取遠程服務器ATN結果,驗證是否是支付寶服務器發來的請求try{using (var client = new HttpClient()){//client.Timeout = 120000;var response = await client.GetAsync(verifyUrl);if (response.IsSuccessStatusCode){byte[] data = await response.Content.ReadAsByteArrayAsync();Encoding.UTF8.GetString(data);return strResult= "true";}}}catch (Exception exp){strResult = "錯誤信息:" + exp.Message;}return string.Empty;}
?public static ContentResult Response_Success(string msg = null)
??????? {
??????????? return new ContentResult
??????????? {
??????????????? Content = msg ?? "success"
??????????? };
??????? }
??????? public static ContentResult ResponseFail(string msg = null)
??????? {
??????????? return new ContentResult
??????????? {
??????????????? Content = msg ?? "fail"
??????????? };
??????? }
}}

?5. 添加一個控制器 PayController

using System;
using System.Collections.Generic;
using Alipay.AopSdk.AspnetCore;
using Alipay.AopSdk.Core;
using Alipay.AopSdk.Core.Domain;
using Alipay.AopSdk.Core.Request;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using Alipay.Demo.PCPayment.Interfaces;
using Microsoft.Extensions.Logging;
namespace Alipay.PCPayment.Controllers
{   /// <summary>/// PC網站支付/// </summary>public class PayController : Controller{private readonly IAlipayService _alipayService;private readonly IAccounts _IAccounts;private readonly ILogger _logger;public PayController(IAlipayService alipayService,  ILogger<PayController> logger){_alipayService = alipayService;_logger = logger;}//_alipayService.Execute();#region 發起支付public IActionResult Index(){return View();}/// <summary>/// 發起支付請求/// </summary>/// <param name="tradeno">外部訂單號,商戶網站訂單系統中唯一的訂單號</param>/// <param name="subject">訂單名稱</param>/// <param name="totalAmout">付款金額</param>/// <param name="itemBody">商品描述</param>/// <returns></returns>
        [HttpPost]public void PayRequest(string tradeno, string subject, string totalAmout, string itemBody){   //    DefaultAopClient client = new DefaultAopClient(Config.Gatewayurl, Config.AppId, Config.PrivateKey, "json", "2.0",//Config.SignType, Config.AlipayPublicKey, Config.CharSet, false);// 組裝業務參數modelAlipayTradePagePayModel model = new AlipayTradePagePayModel{Body = itemBody,Subject = subject,TotalAmount = totalAmout,OutTradeNo = tradeno,ProductCode = "FAST_INSTANT_TRADE_PAY"};AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();// 設置同步回調地址 可以是調試模式地址 并非公網或域名地址 Pay走的是控制器的request.SetReturnUrl("http://190.120.120.01:110/Pay/Callback");// 設置異步通知接收地址 必須是公網或域名地址 Pay走的是控制器的方法request.SetNotifyUrl("http://50.200.50.10:110/Pay/AlipayNotify");// 將業務model載入到request
            request.SetBizModel(model);var response = _alipayService.SdkExecute(request);Console.WriteLine($"訂單支付發起成功,訂單號:{tradeno}");//跳轉支付寶支付 支付網關地址Response.Redirect(Config.Gatewayurl + "?" + response.Body);}#endregion
支付異步回調通知 使用異步通知來獲取支付結果,異步通知即支付寶主動請求我們提供的地址,我們根據請求數據來校驗,獲取支付結果。
#region 支付異步回調通知/// <summary>/// 異步通知即支付寶主動請求我們提供的地址,我們根據請求數據來校驗,獲取支付結果。/// 支付異步回調通知 需配置域名 因為是支付寶主動post請求這個action 所以要通過域名訪問或者公網ip/// </summary>//public async Task<IActionResult> AlipayNotify([FromForm]Dictionary<string,string> NotifyArray)public async Task<IActionResult> AlipayNotify(){/* 實際驗證過程建議商戶添加以下校驗。1、商戶需要驗證該通知數據中的out_trade_no是否為商戶系統中創建的訂單號,2、判斷total_amount是否確實為該訂單的實際金額(即商戶訂單創建時的金額),3、校驗通知中的seller_id(或者seller_email) 是否為out_trade_no這筆單據的對應的操作方(有的時候,一個商戶可能有多個seller_id/seller_email)*/Dictionary<string, string> NotifyArray = GetRequestPost();//通知驗證IDstring notifyId = NotifyArray["notify_id"];try{ if (NotifyArray.Count != 0){ //驗簽以及驗證合作伙伴IDbool flag = _alipayService.RSACheckV1(NotifyArray);if (await Config.VerifyNotifyAsync(notifyId) == "true" && flag){//交易狀態if (NotifyArray["trade_status"] == "TRADE_FINISHED" ||NotifyArray["trade_status"] == "TRADE_SUCCESS"){if (NotifyArray["app_id"] == Config.AppId){ // 修改支付信息以及狀態//return await UpdateAliPayAsyn(NotifyArray); }}await Response.WriteAsync("success");}else{await Response.WriteAsync("fail");}}}catch (Exception e){_logger.LogError("Alipay notify fail, {0}", e);}return View();//string msg = null;//return new ContentResult//{// Content = msg ?? "fail"//}; }/// <summary>/// 更新支付寶支付結果信息/// 判斷該筆訂單是否已經做過處理///如果沒有做過處理,根據訂單號(out_trade_no)在商戶的訂單系統中查到該筆訂單的詳細,并執行商戶的業務程序///請務必判斷請求時的total_amount與通知時獲取的total_fee為一致的///如果有做過處理,不執行商戶的業務程序/// </summary>/// <param name="dict"></param>/// <returns></returns>//private async Task<ContentResult> UpdateAliPayAsyn(Dictionary<string, string> dict)//{// //獲取支付的訂單號// string msg = null;// var orderNO = await accountsOrder.GetOrderAsync(dict["out_trade_no"]);// if (orderNO == null || !accountsOrder.ReadyOrderStatus(orderNO))// {// _logger.LogInformation("充值訂單號不存在");// // return new ContentResult// {// Content = msg ?? "fail"// };// }// //if (!EqualAmountAliPay(order.PayPrice, dict["total_amount"]))// //{// // return AliPay.ResponseFail("訂單金額不匹配");// //}// 更新訂單支付通知結果// //if (await accountsOrder.UpdateOrderAsync(order))// //{// // await accountsOrder.SaveAliPayNotifyDataAsync(dict);// // _logger.LogInformation("[支付寶]支付成功,系統于 " + dtStartTime.ToString() + " 接收到請求,于 " + dict["notify_time"] + " 完成處理,交易流水號:" + dict["trade_no"] + ",交易單號:" + dict["out_trade_no"], "支付寶日志");// // return AliPay.ResponseSuccess();// //}// //else// //{// // _logger.LogInformation("[支付寶]訂單號:" + dict["out_trade_no"] + "狀態:" + dict["trade_status"], "支付寶日志");// // if (dict["trade_status"] == "TRADE_CLOSED")// // {// // return AliPay.ResponseSuccess();// // }// // else// // { //成功// // if (order.PayStatus == 1)// // {// // _logger.LogInformation("[支付寶]已支付過:" + order.RechargeOrderNO, "支付寶日志");// // return AliPay.ResponseSuccess();// // }// // else// // //等待支付// // {// // _logger.LogInformation("[支付寶]未支付:" + order.RechargeOrderNO, "支付寶日志");// // return AliPay.ResponseFail("等待支付");// // }// // }// return new ContentResult// {// Content = msg ?? "fail"// };// }#endregion

同步回調 同步回調即支付成功跳轉回商戶網站

        #region 支付同步回調/// <summary>/// 支付同步回調  同步回調即支付成功跳轉回商戶網站/// </summary>
        [HttpGet]public  IActionResult  Callback(){/* 實際驗證過程建議商戶添加以下校驗。1、商戶需要驗證該通知數據中的out_trade_no是否為商戶系統中創建的訂單號,2、判斷total_amount是否確實為該訂單的實際金額(即商戶訂單創建時的金額),3、校驗通知中的seller_id(或者seller_email) 是否為out_trade_no這筆單據的對應的操作方(有的時候,一個商戶可能有多個seller_id/seller_email)4、驗證app_id是否為該商戶本身。*/Dictionary<string, string> sArray = GetRequestGet();if (sArray.Count != 0){bool flag = _alipayService.RSACheckV1(sArray);if (flag){Console.WriteLine($"同步驗證通過,訂單號:{sArray["out_trade_no"]}");ViewData["PayResult"] = "同步驗證通過";Response.Redirect("http://190.120.120.01:110/");}else{Console.WriteLine($"同步驗證失敗,訂單號:{sArray["out_trade_no"]}");ViewData["PayResult"] = "同步驗證失敗";}}return View();}#endregion#region 解析請求參數private Dictionary<string, string> GetRequestGet(){Dictionary<string, string> sArray = new Dictionary<string, string>();ICollection<string> requestItem = Request.Query.Keys;foreach (var item in requestItem){sArray.Add(item, Request.Query[item]);}return sArray;}/// <summary>/// 獲取返回的請求結果/// </summary>/// <returns></returns>private Dictionary<string, string> GetRequestPost(){Dictionary<string, string> sArray = new Dictionary<string, string>();ICollection<string> requestItem = Request.Form.Keys;foreach (var item in requestItem){sArray.Add(item, Request.Form[item]);}return sArray;}#endregion    }
} }

?7.支付訂單信息頁面

Index.cshtml 支付請求action POST

@{ViewData["Title"] = "PC網站支付";
}
<h2>PC網站支付</h2>
<div class="row"><div class="col-sm-12" s><form  asp-action="PayRequest" method="post" class="form-horizontal" role="form"><div class="form-group"><label for="tradeno" class="control-label col-sm-2">商戶訂單號:</label><div class="col-sm-10"><input type="text" name="tradeno" class="form-control" id="tradeno" value=""/></div></div><div class="form-group"><label for="subject" class="control-label col-sm-2">訂單名稱:</label><div class="col-sm-10"><input type="text" name="subject" class="form-control" id="subject" value="iPhone X" /></div></div><div class="form-group"><label for="totalAmout" class="control-label col-sm-2">付款金額:</label><div class="col-sm-10"><input type="number" min="0.01" name="totalAmout" class="form-control" id="totalAmout" value="99.99" /></div></div><div class="form-group"><label for="itemBody" class="control-label col-sm-2">商品描述:</label><div class="col-sm-10"><input type="text"  name="itemBody" class="form-control" id="itemBody" value="蘋果手機" /></div></div><div class="form-group"><div class="col-sm-10 col-sm-offset-2"><button class="btn btn-success btn-block">付款</button><p class="help-block text-center">如果您點擊“付款”按鈕,即表示您同意該次的執行操作。</p></div></div></form></div></div><script>function GetDateNow() {var vNow = new Date();var sNow = "";sNow += String(vNow.getFullYear());sNow += String(vNow.getMonth() + 1);sNow += String(vNow.getDate());sNow += String(vNow.getHours());sNow += String(vNow.getMinutes());sNow += String(vNow.getSeconds());sNow += String(vNow.getMilliseconds());document.getElementById("tradeno").value =  sNow;}GetDateNow();
</script>

?8.配置系統啟動項目信息

Startup.cs

public class Startup{public Startup(IConfiguration configuration){Configuration = configuration;}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.AddMvc();Console.WriteLine(Configuration["Alipay:AlipayPublicKey"]);services.AddAlipay(options =>{options.AlipayPublicKey = Configuration["Alipay:AlipayPublicKey"];options.AppId = Configuration["Alipay:AppId"];options.CharSet = Configuration["Alipay:CharSet"];options.Gatewayurl = Configuration["Alipay:Gatewayurl"];options.PrivateKey = Configuration["Alipay:PrivateKey"];options.SignType = Configuration["Alipay:SignType"];options.Uid = Configuration["Alipay:Uid"];}).AddAlipayF2F();}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory){loggerFactory.AddConsole(Configuration.GetSection("Logging"));loggerFactory.AddDebug();if (env.IsDevelopment()){app.UseDeveloperExceptionPage();app.UseBrowserLink();}else{app.UseExceptionHandler("/Home/Error");}app.UseStaticFiles();app.UseMvc(routes =>{routes.MapRoute(name: "default",template: "{controller=Home}/{action=Index}/{id?}");});}}

appsettings.json

{"Logging": {"IncludeScopes": false,"LogLevel": {"Default": "Error"}},"WriteTo": ["LiterateConsole",{"Name": "RollingFile","Args": { "pathFormat": "logs\\log-{Date}.txt" }}],"Alipay": {"AlipayPublicKey": "/fVCQx+B+++++HLB7K9yTNoBWBGsOsNpTiErj2wqdyOp8KVSp/5P1","AppId": "2016******03","CharSet": "UTF-8","Gatewayurl": "https://openapi.alipaydev.com/gateway.do","PrivateKey": "/eQ1ykzA5hecyw4K/+/pIFjLm/M/+/vj0gy+eqabgVUjyOLDuEc"\",": null,"SignType": "RSA2","Uid": "208********2"}
}

9、支付演示
支付請求頁面

?

跳轉到支付寶支付網關沙箱地址

?拿起手機APP沙箱版的進行掃碼支付 或者進行沙箱賬號買家賬戶登錄支付

支付成功提示頁面

?

轉載于:https://www.cnblogs.com/Warmsunshine/p/7904609.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/370435.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/370435.shtml
英文地址,請注明出處:http://en.pswp.cn/news/370435.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何在redhat8里使用gcc命令_如何使用who命令檢查用戶登錄信息

請關注本頭條號&#xff0c;每天堅持更新原創干貨技術文章。如需學習視頻&#xff0c;請在微信搜索公眾號“智傳網優”直接開始自助視頻學習1. 前言本教程主要介紹如何使用who命令檢查用戶登錄信息。如何使用who命令檢查用戶登錄信息Linux中的who命令列出了系統上的所有登錄用戶…

研究僵局–第4部分:修復代碼

在這個簡短的博客系列的最后BadTransferOperation中&#xff0c;我一直在討論分析死鎖&#xff0c;我將修復BadTransferOperation代碼。 如果您看過本系列的其他博客 &#xff0c;那么您將知道&#xff0c;為了達到這一點&#xff0c;我創建了死鎖的演示代碼&#xff0c;展示了…

chrome插件2

轉自&#xff1a;http://www.codeceo.com/article/15-chrome-extension.html 1. Web Developer 支持Chrome的Web Developer擴展&#xff0c;允許你通過添加一個小工具欄來使用不同的工具。 官方網站&#xff1a;https://chrome.google.com/webstore/detail/web-developer/bfbam…

java月歷組件_vue之手把手教你寫日歷組件

---恢復內容開始---1.日歷組件1.分析功能&#xff1a;日歷基本功能&#xff0c;點擊事件改變日期&#xff0c;樣式的改變1.結構分析&#xff1a;html1.分為上下兩個部分2.上面分為左按鈕&#xff0c;中間內容展示&#xff0c;右按鈕下面分為周幾展示和日期展示3.基本結構頁面ht…

HTML5和css3

超鏈接 <a target"頁面打開位置" href"鏈接地址">內容</a>target:_blank 重新打開一個頁面target:_self 當前頁面打開 1.頁面地址&#xff1a; 基礎功能&#xff0c;用于進入該鏈接的頁面&#xff1b; 2.錨點&#xff1a; 需要給標簽名定義id…

python下載顯示文件丟失_Microsoft.PythonTools.resources.dll

我該如何安裝從金山毒霸下載的DLL文件&#xff1f;一&#xff1a;1、從金山毒霸下載壓縮文件。2、將DLL文件解壓到電腦上的某個地方。3、把該文件跟要求使用它的程序放在同一路徑上。注意32位程序需要使用32位的DLL文件&#xff0c;64位程序需要使用64位的DLL文件。否則會出現0…

maven project module 依賴項目創建 ---轉

一、創建Maven Project 1.右擊 --> New --> Other&#xff0c;--> Maven --> Maven Project --> Next 2.如下圖&#xff0c;選中Create a simple project --> Next 3.輸入Group Id, Artifact Id, Version, Packaging選擇pom&#xff0c;因為創建的Maven Pr…

java soot_正確執行3個地址代碼的SOOT API

我在運行SOOT API時遇到問題 . 我正在使用java -cp soot-2.5.0.jar soot.Main -f jimple test我遇到以下錯誤&#xff1a;Exception in thread "main" java.lang.RuntimeException: Could not load classfile: java.io.ObjectInputStream atat soot.coffi.Util.resol…

JSF AJAX請求的會話超時處理

JSF AJAX請求的會話超時處理 當我們使用AJAX行為開發JSF應用程序時&#xff0c;在處理Ajax請求超時場景時可能會遇到問題。 例如&#xff0c;如果您使用的是基于J2EE表單的身份驗證&#xff0c;則會話超時后應將正常請求重定向到登錄頁面。 但是&#xff0c;如果您的請求是AJAX…

linux常見命令搜集

查找根目錄下txt和pdf文件 find / \( -name "*.txt" -o -name "*.pdf" \) -print 正則查找根目錄下所有的txt和pdf文件 find / -regex ".*\(\.txt|\.pdf\)$"查找所有非txt文本 find . ! -name "*.txt" -print制定搜索深度 find ~ -max…

前端html,css基礎總結

0.1、css引入界面的方式: 內聯式:通過標簽的style屬性&#xff0c;在標簽上直接寫樣式。 <div style"width:100px; height:100px; background:red "></div> 嵌入式:通過style標簽&#xff0c;在網頁上創建嵌入的樣式表。 <style type"text/css&q…

知乎python練手的_Python—爬蟲之初級實戰項目:爬取知乎任一作者的文章練手

爬蟲之初級實戰項目&#xff1a;爬取知乎任一作者的文章練手在正式上代碼之前&#xff0c;先過一遍之前所學知識的框架內容&#xff0c;溫故而知新&#xff01;&#xff01;&#xff01;接下來我們直接上代碼&#xff0c;一定要手敲代碼、手敲代碼、手敲代碼&#xff01;&#…

java url幫助類_Spring居然還提供了這么好用的URL工具類

1. 前言開發中我們經常會操作 URL&#xff0c;比如提取端口、提取路徑以及最常用的提取參數等等。很多時候需要借助于一些第三方類庫或者自己編寫工具類來實現&#xff0c;今天胖哥給大家介紹一種方法&#xff0c;無需新的類庫引入&#xff0c;只要你使用了 Spring Web 模塊都可…

Java并發之CyclicBarria的使用(二)

Java并發之CyclicBarria的使用&#xff08;二&#xff09; 一.簡介 之前借助于其他大神寫過一篇關于CyclicBarria用法的博文&#xff0c;但是內心總是感覺絲絲的愧疚&#xff0c;因為筆者喜歡原創&#xff0c;而不喜歡去轉載一些其他的文章&#xff0c;為此筆者自己原創了一個C…

需加裝飾——裝飾模式

裝飾模式指的是在不必改變原類文件和使用繼承的情況下&#xff0c;動態地擴展一個對象的功能。它是通過創建一個包裝對象&#xff0c;也就是裝飾來包裹真實的對象。 類圖分析 我們先假設一個業務場景&#xff0c;有三種房子需要裝修&#xff0c;分別是公寓&#xff0c;木屋和別…

Java正則表達式教程及示例

當我開始使用Java時&#xff0c;正則表達式對我來說是一場噩夢。 本教程旨在幫助您掌握Java正則表達式&#xff0c;并讓我定期返回以刷新我的正則表達式學習。 什么是正則表達式&#xff1f; 正則表達式定義字符串的模式。 正則表達式可用于搜索&#xff0c;編輯或處理文本。…

Vue2.0 --- vue-cli腳手架中全局引入JQ

第一步&#xff1a;安裝jQuery npm/cmpn方式安裝(默認安裝1.7.X版本的JQ) npm/cnpm install jQuery 如果想安裝更高版本的JQ那么可以選擇在package.json文件下面這個位置添加代碼斷&#xff08;當前圖片安裝的是2.2.3版本&#xff0c;如果想安裝更高或者其他可以更改版本號&…

python筆記全_Python筆記

一、數據結構和序列1.1、元組&#xff1a;有一種固定長度&#xff0c;不可修改的python對象序列tup 1,2,3 tup : (1,2,3)tup tuple([4,0,2]) tup : (4,0,2)tup[0] 4元組添加元素&#xff1a;tup (["foo",[1,2],True])tup[1].append(3)tup : ("foo",[1,…

java 分布式編譯_linux分布式編譯distcc和ccache的部署

unset LANGUAGEexport LANG"en"cd /home/kingsoftmkdir distcccd distccrpm包用&#xff1a;rpm -ivh ...bz2包用&#xff1a;tar -xvf ...進入distcc解壓后的目錄./configure && make && make installmkdir /usr/lib/distccmkdir /usr/lib/distcc/b…

Unity——用UnityEditor拷貝FBX中的AnimationClip

最近有個新需求&#xff0c;要用代碼添加動畫的事件&#xff0c;但是Unity不能直接修改FBX中的AnimationClip 在Animation窗口中可以看到&#xff0c;AnimationClip是Read-Only狀態&#xff0c;用代碼修改這個AnimationClip也是不會生效的&#xff0c;包括用代碼添加事件 解決方…