前面讨论了微信支付,接下来聊聊支付宝的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支付的更多相关文章

  1. 支付宝app支付java后台流程、原理分析(含nei wang chuan tou)

    java版支付宝app支付流程及原理分析 本实例是基于springmvc框架编写     一.流程步骤         1.执行流程           当手机端app(就是你公司开发的app)在支付 ...

  2. 支付宝APP支付IOS手机端java后台版

    版权声明:http://blog.csdn.net/u012131769/article/details/76639527#t8 转载:http://blog.csdn.net/u012131769/ ...

  3. 支付宝APP支付之Java后台生成签名具体步骤

    /** *支付宝支付 * @param orderId 订单编号 * @param actualPay 实际支付金额 * @return */ private String getOrderInfoB ...

  4. H5使用codovar插件实现支付宝支付(支付宝APP支付模式,前端)

    H5打包的app实现支付及支付宝支付,本章主要详解支付宝支付,微信支付请查看另一篇“H5使用codovar插件实现微信支付(微信APP支付模式,前端)” ps:本文只试用H5开发的,支付宝 APP支付 ...

  5. 支付宝APP支付开发- IOException : DER input, Integer tag error

    支付宝APP支付Java开发报错: 1 java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: I ...

  6. 支付宝APP支付开发- IOException : DerInputStream.getLength(): lengthTag=127, too big.

    支付宝APP支付Java开发报错: IOException : DerInputStream.getLength(): lengthTag=127, too big. 后来排查是因为没有设置私钥.

  7. Android版-支付宝APP支付

    此项目已开源 赶快来围观 Start支持下吧 [客户端开源地址-JPay][服务端端开源地址-在com.javen.alipay 包名下] 上一篇详细介绍了微信APP支付 点击这里 此篇文章来详细介绍 ...

  8. 支付宝app支付服务端流程

    支付宝APP支付服务端详解 前面接了微信支付,相比微信支付,支付宝APP支付提供了支付封装类,下面将实现支付宝APP支付.订单查询.支付结果异步通知.APP支付申请参数说明,以及服务端返回APP端发起 ...

  9. 微信、支付宝App支付-JPay0.0.2发布

    JPay 对微信App支付.支付宝App支付的二次封装,对外提供一个相对简单的接口以及支付结果的回调 GitHub:https://github.com/Javen205/JPay OsChina:h ...

随机推荐

  1. BUUCTF-Web-Warm Up(CVE-2018-12613)

    题目(虽然是Warm up,但一点也不简单): 打开只有图片,源码里面提示了source.php 查看source.php: php代码里又提到了hint,去查看一下: 提示flag在如上图文件名里面 ...

  2. 神奇的requestAnimationFrame解决传统定时器bug

    可能你还没见过这个东西是个啥,其实他就是类似于setTimeout和setInterval,然而它与setTimeout和setInterval又有所不同,requestAnimationFrame不 ...

  3. 通过POI实现上传EXCEL的批量读取数据写入数据库

    最近公司新增功能要求导入excel,并读取其中数据批量写入数据库.于是就开始了这个事情,之前的文章,记录了上传文件,本篇记录如何通过POI读取excel数据并封装为对象上传. 上代码: 1.首先这是一 ...

  4. Java生鲜电商平台-小程序或者APP优惠券的设计与源码实战

    Java生鲜电商平台-小程序或者APP优惠券的设计与源码实战 说明:Java生鲜电商平台-小程序或者APP优惠券的设计与源码实战,优惠券是一种常见的促销方式,在规定的周期内购买对应商品类型和额度的商品 ...

  5. 01 认识python

    python介绍 python的创始⼈为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决⼼ 开发⼀个新的脚本解释程序,作为ABC语 ...

  6. Spring Boot Mybatis 使用教程

    Mybatis 在当下互联网开发环境,十分重要.本章主要讲述 Mybatis 如何使用. 从本系列开始,都需要用到 mysql 数据库 和其他一些参考的数据库.请准备相关环节.本章需要以下环境支撑: ...

  7. k8s 的pod进阶

    容器探测的具体实现方法:三种探针类型 ExecAction.TCPSocketAction.HTTPGetAction lifecycle <Object> Actions that th ...

  8. 使用命令将单个java文件打包为jar

    思路:先将java文件编译为class文件,然后再打包为jar 参考博文:https://www.cnblogs.com/sxdcgaq8080/p/8126770.html http://www.m ...

  9. 吴裕雄--天生自然Numpy库学习笔记:NumPy 迭代数组

    import numpy as np a = np.arange(6).reshape(2,3) print ('原始数组是:') print (a) print ('\n') print ('迭代输 ...

  10. netty实现websocket客户端(附:测试服务端代码)

    1,客户端启动类 package test3; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.Unpooled; import ...