.Net后台实现支付宝APP支付
前面讨论了微信支付,接下来聊聊支付宝的APP支付(新款支付宝支付)。其实这些支付原理都一样,只不过具体到每个支付平台,所使用的支付配置参数不同,返回至支付端的下单参数也不同。
话不多说,直接上代码。
在App.Pay项目中使用NuGet管理器添加引用Alipay.AopSdk,也可以不添加引用,将官方SDK源码放至项目中。
添加完引用后,我们就可以开工了,新建文件夹AliPay,在文件夹中新建AliPayConfig类,存放支付宝APP支付所需的参数,同样,这些参数我也放在了配置文件中。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Configuration; namespace App.Pay.AliPay
{
public class AliPayConfig
{
//支付宝网关地址
public static string serviceUrl = WebConfigurationManager.AppSettings["aliServiceUrl"].ToString(); //应用ID
public static string appId = WebConfigurationManager.AppSettings["aliAppId"].ToString(); //开发者私钥,由开发者自己生成
public static string privateKey = WebConfigurationManager.AppSettings["aliPrivateKey"].ToString(); //支付宝的应用公钥
public static string publicKey = WebConfigurationManager.AppSettings["aliPublicKey"].ToString(); //支付宝的支付公钥
public static string payKey = WebConfigurationManager.AppSettings["aliPayKey"].ToString(); //服务器异步通知页面路径
public static string notify_url = WebConfigurationManager.AppSettings["aliNotifyUrl"].ToString(); //页面跳转同步通知页面路径
public static string return_url = WebConfigurationManager.AppSettings["aliReturnUrl"].ToString(); //参数返回格式,只支持json
public static string format = WebConfigurationManager.AppSettings["aliFormat"].ToString(); // 调用的接口版本,固定为:1.0
public static string version = WebConfigurationManager.AppSettings["aliVersion"].ToString(); // 商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2
public static string signType = WebConfigurationManager.AppSettings["aliSignType"].ToString(); // 字符编码格式 目前支持utf-8
public static string charset = WebConfigurationManager.AppSettings["aliCharset"].ToString(); // false 表示不从文件加载密钥
public static bool keyFromFile = false; // 日志记录
public static string LogPath = WebConfigurationManager.AppSettings["AliLog"].ToString();
}
}
支付宝支付中有个沙箱测试环境,我们可以先在沙箱环境下调通整个流程(沙箱支付宝里面的钱是虚拟的哦)。介绍一下这几个支付参数。
①aliServiceUrl支付宝网关地址,固定不变的,沙箱环境下用沙箱的,正式环境下用正式的。
②aliAppId支付宝APPID,aliPrivateKey支付宝应用私钥,aliPublicKey支付宝应用公钥,aliPayKey支付宝公钥
aliPublicKey和aliPayKey是不一样的,一个是应用公钥,一个是支付宝公钥,回调接口中验签使用的是支付宝公钥
③aliNotifyUrl服务器通知,aliReturnUrl网页重定向通知(暂时没有用到)。主要使用到的还是aliNotifyUrl,买家付完款后(trade_status=WAIT_SELLER_SEND_GOODS),支付宝服务端会自动向商户后台发送支付回调通知,同样,商户在支付回调通知中修改订单相关状态,反馈给支付宝success,表示成功接收到回调,这个状态下支付宝不会再继续通知商户后台。
④aliFormat、aliVersion、aliSignType、aliCharset这几个参数都是固定不变的,签名的时候使用。
<!--支付宝app支付-->
<add key="aliServiceUrl" value=""/>
<add key="aliAppId" value="" />
<add key="aliPrivateKey" value=""/>
<add key="aliPublicKey" value="" />
<add key="aliPayKey" value="" />
<add key="aliNotifyUrl" value="" />
<add key="aliReturnUrl" value="" />
<add key="aliFormat" value="json" />
<add key="aliVersion" value="1.0" />
<add key="aliSignType" value="RSA2" />
<add key="aliCharset" value="utf-8" />
新建AliPay类
using Aop.Api;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace App.Pay.AliPay
{
public class AliPay
{
public static IAopClient GetAlipayClient()
{
string serviceUrl = AliPayConfig.serviceUrl; string appId = AliPayConfig.appId; string privateKey = AliPayConfig.privateKey; string publivKey = AliPayConfig.publicKey; string format = AliPayConfig.format; string version = AliPayConfig.version; string signType = AliPayConfig.signType; string charset = AliPayConfig.charset; bool keyFromFile = AliPayConfig.keyFromFile; IAopClient client = new DefaultAopClient(serviceUrl, appId, privateKey, format, version, signType, publivKey, charset, keyFromFile); ; return client;
}
}
}
接下来就是业务中的具体调用
using Aop.Api;
using Aop.Api.Domain;
using Aop.Api.Request;
using Aop.Api.Response;
using Aop.Api.Util;
using App.Common.Extension;
using App.Pay.AliPay;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace App.WebTest.Controllers
{
public class AliPayController : BaseController
{
/// <summary>
/// 订单编号
/// </summary>
/// <param name="oidStr"></param>
/// <returns></returns>
public ActionResult AliPay(string oidStr)
{
#region 验证订单有效 if (string.IsNullOrEmpty(oidStr))
{
return Json(false, "OrderError");
} int[] oIds = Serialize.JsonTo<int[]>(oidStr); decimal payPrice = ; ///订单验证,统计订单总金额 #endregion #region 统一下单
try
{
var notify_url = AliPayConfig.notify_url;
var return_url = AliPayConfig.return_url;
IAopClient client = Pay.AliPay.AliPay.GetAlipayClient();
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
//SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.Subject = "商品购买";
model.TotalAmount = payPrice.ToString("F2");
model.ProductCode = "QUICK_MSECURITY_PAY";
Random rd = new Random();
var payNum = DateTime.Now.ToString("yyyyMMddHHmmss") + rd.Next(, ).ToString().PadLeft(, '');
model.OutTradeNo = payNum;
model.TimeoutExpress = "30m";
request.SetBizModel(model);
request.SetNotifyUrl(notify_url);
//request.SetReturnUrl(return_url);
//这里和普通的接口调用不同,使用的是sdkExecute
AlipayTradeAppPayResponse response = client.SdkExecute(request); //统一下单
//OrderBll.Value.UpdateOrderApp(oIds, payNum); return Json(true, new { response.Body }, "OK");
}
catch (Exception ex)
{
return Json(new { Result = false, msg = "缺少参数" });
}
#endregion
} /// <summary>
/// 页面跳转同步通知页面
/// </summary>
/// <returns></returns>
public ActionResult ReturnUrl()
{
Pay.Log Log = new Pay.Log(Pay.AliPay.AliPayConfig.LogPath);
Log.Info("ReturnUrl", "支付页面同步回调");
//将同步通知中收到的所有参数都存放到map中
IDictionary<string, string> map = GetRequestGet();
if (map.Count > ) //判断是否有带返回参数
{
try
{
//支付宝的公钥
string alipayPublicKey = AliPayConfig.payKey;
string signType = AliPayConfig.signType;
string charset = AliPayConfig.charset;
bool keyFromFile = false;
// 获取支付宝GET过来反馈信息
bool verify_result = AlipaySignature.RSACheckV1(map, alipayPublicKey, charset, signType, keyFromFile);
if (verify_result)
{
// 验证成功
return Json(new { Result = true, msg = "验证成功" });
}
else
{
Log.Error("AliPayNotifyUrl", "支付验证失败");
return Json(new { Result = false, msg = "验证失败" });
}
}
catch (Exception e)
{
//throw new Exception(e.Message);
return Json(new { Result = false, msg = "验证失败" });
Log.Error("AliPayNotifyUrl", "支付验证失败");
}
}
else
{
return Json(new { Result = false, msg = "无返回参数" });
}
} /// <summary>
/// 服务器异步通知页面
/// </summary>
public void AliPayNotifyUrl()
{
Pay.Log Log = new Pay.Log(AliPayConfig.LogPath);
Log.Info("AliPayNotifyUrl", "支付页面异步回调");
IDictionary<string, string> map = GetRequestPost(); if (map.Count > )
{
try
{
string alipayPublicKey = AliPayConfig.payKey;
string signType = AliPayConfig.signType;
string charset = AliPayConfig.charset;
bool keyFromFile = false; bool verify_result = AlipaySignature.RSACheckV1(map, alipayPublicKey, charset, signType, keyFromFile);
Log.Info("AliPayNotifyUrl验签", verify_result + ""); //验签成功后,按照支付结果异步通知中的描述,对支付结果中的业务内容进行二次校验,校验成功后再response中返回success并继续商户自身业务处理,校验失败返回false
if (verify_result)
{
//商户订单号
string out_trade_no = map["out_trade_no"];
//支付宝交易号
string trade_no = map["trade_no"];
//交易创建时间
string gmt_create = map["gmt_create"];
//交易付款时间
string gmt_payment = map["gmt_payment"];
//通知时间
string notify_time = map["notify_time"];
//通知类型 trade_status_sync
string notify_type = map["notify_type"];
//通知校验ID
string notify_id = map["notify_id"];
//开发者的app_id
string app_id = map["app_id"];
//卖家支付宝用户号
string seller_id = map["seller_id"];
//买家支付宝用户号
string buyer_id = map["buyer_id"];
//实收金额
string receipt_amount = map["receipt_amount"];
//交易状态
string return_code = map["trade_status"]; //交易状态TRADE_FINISHED的通知触发条件是商户签约的产品不支持退款功能的前提下,买家付款成功;
//或者,商户签约的产品支持退款功能的前提下,交易已经成功并且已经超过可退款期限
//状态TRADE_SUCCESS的通知触发条件是商户签约的产品支持退款功能的前提下,买家付款成功
if (return_code == "TRADE_FINISHED" || return_code == "TRADE_SUCCESS")
{
string msg; Log.Error("AliPayNotifyUrl", receipt_amount + "==" + trade_no + "==" + return_code + "==" + out_trade_no + "==" + gmt_payment); //判断该笔订单是否在商户网站中已经做过处理
///支付回调的业务处理
//bool res = OrderBll.Value.CompleteAliPay(receipt_amount, trade_no, return_code, out_trade_no, gmt_payment, out msg);
bool res = true; if (res == false)
{
Response.Write("添加支付信息失败!");
}
Log.Error("AliPayNotifyUrl", "支付成功");
Response.Write("success"); //请不要修改或删除
}
}
else
{
//验证失败
Log.Error("AliPayNotifyUrl", "支付验证失败");
Response.Write("验证失败!");
}
}
catch (Exception e)
{
Response.Write("添加支付信息失败!");
Log.Error("AliPayNotifyUrl", "添加支付信息失败");
}
}
else
{
//无返回参数
Response.Write("无返回参数!");
Log.Error("AliPayNotifyUrl", "无返回参数");
}
}
//[AllowUser]
//public ActionResult TestAliPay()
//{ // var receipt_amount = "0.01";
// var trade_no = "20181226220013.......";
// var return_code = "TRADE_SUCCESS";
// var out_trade_no = "20181226103124129";
// var gmt_payment = "2018-12-26 10:31:29"; // string msg = "";
// bool res = OrderBll.Value.CompleteAliPay(receipt_amount, trade_no, return_code, out_trade_no, gmt_payment, out msg); // return Json(res);
//} /// <summary>
/// 获取支付宝Get过来的通知消息,并以“参数名=参数值”的形式组成数组
/// </summary>
/// <returns></returns>
public IDictionary<string, string> GetRequestGet()
{
Pay.Log Log = new Pay.Log(Pay.AliPay.AliPayConfig.LogPath);
int i = ;
IDictionary<string, string> sArry = new Dictionary<string, string>();
NameValueCollection coll;
coll = Request.QueryString; String[] requstItem = coll.AllKeys; for (i = ; i < requstItem.Length; i++)
{
Log.Info("GetRequestGet", requstItem[i] + ":" + Request.QueryString[requstItem[i]]);
sArry.Add(requstItem[i], Request.QueryString[requstItem[i]]);
} return sArry;
} /// <summary>
/// 获取支付宝POST过来通知消息,并以“参数名=参数值”的形式组成数组
/// </summary>
/// <returns>request回来的信息组成的数组</returns>
public IDictionary<string, string> GetRequestPost()
{
Pay.Log Log = new Pay.Log(Pay.AliPay.AliPayConfig.LogPath);
int i = ;
IDictionary<string, string> sArray = new Dictionary<string, string>();
NameValueCollection coll; //Load Form variables into NameValueCollection variable.
coll = Request.Form; // Get names of all forms into a string array.
String[] requestItem = coll.AllKeys;
for (i = ; i < requestItem.Length; i++)
{
Log.Info("GetRequestPost", requestItem[i] + ":" + Request.Form[requestItem[i]]);
sArray.Add(requestItem[i], Request.Form[requestItem[i]]);
} return sArray;
}
}
}
.Net后台实现支付宝APP支付的更多相关文章
- 支付宝app支付java后台流程、原理分析(含nei wang chuan tou)
java版支付宝app支付流程及原理分析 本实例是基于springmvc框架编写 一.流程步骤 1.执行流程 当手机端app(就是你公司开发的app)在支付 ...
- 支付宝APP支付IOS手机端java后台版
版权声明:http://blog.csdn.net/u012131769/article/details/76639527#t8 转载:http://blog.csdn.net/u012131769/ ...
- 支付宝APP支付之Java后台生成签名具体步骤
/** *支付宝支付 * @param orderId 订单编号 * @param actualPay 实际支付金额 * @return */ private String getOrderInfoB ...
- H5使用codovar插件实现支付宝支付(支付宝APP支付模式,前端)
H5打包的app实现支付及支付宝支付,本章主要详解支付宝支付,微信支付请查看另一篇“H5使用codovar插件实现微信支付(微信APP支付模式,前端)” ps:本文只试用H5开发的,支付宝 APP支付 ...
- 支付宝APP支付开发- IOException : DER input, Integer tag error
支付宝APP支付Java开发报错: 1 java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: I ...
- 支付宝APP支付开发- IOException : DerInputStream.getLength(): lengthTag=127, too big.
支付宝APP支付Java开发报错: IOException : DerInputStream.getLength(): lengthTag=127, too big. 后来排查是因为没有设置私钥.
- Android版-支付宝APP支付
此项目已开源 赶快来围观 Start支持下吧 [客户端开源地址-JPay][服务端端开源地址-在com.javen.alipay 包名下] 上一篇详细介绍了微信APP支付 点击这里 此篇文章来详细介绍 ...
- 支付宝app支付服务端流程
支付宝APP支付服务端详解 前面接了微信支付,相比微信支付,支付宝APP支付提供了支付封装类,下面将实现支付宝APP支付.订单查询.支付结果异步通知.APP支付申请参数说明,以及服务端返回APP端发起 ...
- 微信、支付宝App支付-JPay0.0.2发布
JPay 对微信App支付.支付宝App支付的二次封装,对外提供一个相对简单的接口以及支付结果的回调 GitHub:https://github.com/Javen205/JPay OsChina:h ...
随机推荐
- json 字符串 <----> json 对象
一,字符串 -->JSON对象 1,转换函数 JSON.parse(json_str): 2,$.parseJSON(json_str): 用的是 jquery 的插件 所以需要引入 jq. ...
- C语言 排序算法
冒泡排序 冒泡排序(英语:Bubble Sort)是一种简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序(如从大到小.首字母从A到Z)错误就把他们交换过来. 过程演示: 选 ...
- 支付接口API
//微信支付SDK https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
- 【CSS选择器】
" 目录 一.介绍 二.语法 三.引入方式 1. 行内样式 2. 嵌入式 3. 外部样式 四.选择器 1. 基本选择器 2. 组合选择器 3. 属性选择器 4. 不常用选择器 5. 分组和嵌 ...
- 「CF891C」Envy
传送门 Luogu 解题思路 考虑最小生成树的几个性质: 所有最小生成树中边权相等的边的条数相等 在任意一颗最小生成树中,边权相等的边所联通的点集一定 那么我们考虑把边权相等的边单独拿出来考虑. 每次 ...
- php 算false的情况
四.PHP中算false的情况 1.Boolan false 2.整形 0 3.浮点型 0.0 4.字符串"" "0" ("0.0" &qu ...
- JDBC statement的常用方法
Statement接口: 用于执行静态SQL语句并返回它所生成结果的对象. 三种Statement类: Statement: 由createStatement创建,用于发送简单的SQL语句(最好是不带 ...
- [面试必备]深入理解Java的volatile关键字
前言 在Java并发编程中,volatile关键字有着至关重要的作用,在面试中也常常会是必备的一个问题.本文将会介绍volatile关键字的作用以及其实现原理. volatile作用 volatile ...
- ZOJ1006 Do the Untwist
简单模拟~ #include<bits/stdc++.h> using namespace std; ; int a[maxn]; unordered_map<char,int> ...
- 24 JavaScript对象访问器&JavaScript对象构造器
ES5引入了Getter和Setter Getter和Setter允许定义对象访问器 JavaScript Getter(get关键字):获取对象属性 <script> var perso ...