附上支付宝接口API统一支付文档:
对于PC网站支付的交易,在用户支付完成之后,支付宝会根据API中商户传入的return_url参数,通过GET请求的形式将部分支付结果参数通知到商户系统。
公共参数:
参数 | 类型 | 是否必填 | 最大长度 | 描述 | 示例值 |
---|---|---|---|---|---|
app_id | String | 是 | 32 | 支付宝分配给开发者的应用ID | 2016040501024706 |
method | String | 是 | 128 | 接口名称 | alipay.trade.page.pay.return |
sign_type | String | 是 | 10 | 签名算法类型,目前支持RSA2和RSA,推荐使用RSA2 | RSA2 |
sign | String | 是 | 256 | 支付宝对本次支付结果的签名,开发者必须使用支付宝公钥验证签名 | 详见示例 |
charset | String | 是 | 10 | 编码格式,如utf-8,gbk,gb2312等 | utf-8 |
timestamp | String | 是 | 19 | 前台回跳的时间,格式"yyyy-MM-dd HH:mm:ss" | 2016-08-11 19:36:01 |
version | String | 是 | 3 | 调用的接口版本,固定为:1.0 | 1.0 |
auth_app_id | String | 是 | 32 | 授权方的appid注:由于本接口暂不开放第三方应用授权,因此auth_app_id=app_id | 2016040501024706 |
业务参数:
参数 | 类型 | 是否必填 | 最大长度 | 描述 | 示例值 |
---|---|---|---|---|---|
out_trade_no | String | 是 | 64 | 商户网站唯一订单号 | 70501111111S001111119 |
trade_no | String | 是 | 64 | 该交易在支付宝系统中的交易流水号。最长64位。 | 2016081121001004630200142207 |
total_amount | Price | 是 | 9 | 该笔订单的资金总额,单位为RMB-Yuan。取值范围为[0.01,100000000.00],精确到小数点后两位。 | 9.00 |
seller_id | String | 是 | 16 | 收款支付宝账号对应的支付宝唯一用户号。 以2088开头的纯16位数字 | 2088111111116894 |
https://m.alipay.com/GkSL?total_amount=0.10×tamp=2016-11-02+18%3A34%3A19&sign=G3WI0czviMAOzS5t0fYaDgK32sGpjkkXYVFTpYMtgX8JaXLiGiUTO%2F2IHogcCFT96jBCLZ6IsNzd%2BmxkB%2FRuwG%2F7naQk1qReuORMkrB5cpBf9U40bIUoCmSNqtANsTE2UPV7GKegYG2RqoCRScTmeFAFHj5L7zsM%2BLuYb9mqN3g%3D&trade_no=2016110221001004330228438026&sign_type=RSA2&auth_app_id=2014073000007292&charset=UTF-8&seller_id=2088411964605312&method=alipay.trade.page.pay.return&app_id=2014073000007292&out_trade_no=20150g320g010101001&version=1.0
错误码 | 错误描述 | 解决方案 |
---|---|---|
SYSTEM_ERROR | 系统异常 | 联系支付宝小二(联系支付宝文档右边的客服头像或到支持中心咨询) |
PAYMENT_UNKNOW | 支付结果未知 | 联系支付宝小二(联系支付宝文档右边的客服头像或到支持中心咨询) |
PARTNER_ERROR | 合作伙伴信息不正确 | 请确认partnerId是否正确 |
INVALID_PARAMETER | 参数非法 | 请确认接入是否规范,如参数长度、格式等 |
SELLER_NOT_EXIST | 卖家不存在 | 请确认传入的卖家信息是否正确 |
INVALID_RECEIVE_ACCOUNT | 卖家不在设置的收款账户列表之中 | 请确认签约的收款限制集中是否包含所传卖家 |
TRADE_BUYER_NOT_MATCH | 交易买家不匹配 | 该笔交易已经创建,买家与本次买家不一致,需更换外部交易号或者更换为该笔交易的买家 |
CONTEXT_INCONSISTENT | 交易信息被篡改 | 该笔交易已经创建,请检查请求里的商品名称、金额、买卖家等信息与已存交易里的是否一致 |
TRADE_STATUS_ERROR | 交易状态不合法 | 检查交易状态,是否已经支付完成或者超时关闭 |
TRADE_HAS_SUCCESS | 交易已经支付 | 交易已经支付,若需要再次发起交易,请更换外部交易号 |
TRADE_HAS_CLOSE | 交易已经关闭 | 交易已经关闭,若需要再次发起交易,请更换外部交易号 |
EXIST_FORBIDDEN_WORD | 订单信息中包含违禁词 | 请更换订单信息 |
TOTAL_FEE_EXCEED | 订单金额超过限额 | 订单总金额必须大于等于0.01,小于等于100000000 |
TRADE_SETTLE_ERROR | 交易结算异常 | 检查结算信息(分账参数或者结算到卡参数)是否正确 |
ACCESS_FORBIDDEN | 商户没有使用该产品的权限 | 检查是否正确签约(产品是否正确、签约是否生效) |
BUYER_ENABLE_STATUS_FORBID | 买家状态非法,无法继续交易 | 更换买家 |
TRADE_PAYINFO_INCONSISTEN |
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Collections.Specialized;
using System.Collections.Generic;
using CS;
using ZhClass;
using Newtonsoft.Json;
using System.Text;
///
/// ///页面功能说明///
/// 该页面可在本机电脑测试
/// 可放入HTML等美化页面的代码、商户业务逻辑程序代码
/// 该页面可以使用ASP.NET开发工具调试,也可以使用写文本函数LogResult进行调试
///
public partial class return_url : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//商户订单号
string out_trade_no = "";
try
{
SortedDictionary sPara = GetRequestGet();
//商户订单号
out_trade_no = Request.QueryString["out_trade_no"];
//支付宝交易号
string trade_no = Request.QueryString["trade_no"];
//交易状态
string trade_status = Request.QueryString["trade_status"];
if (sPara.Count > 0)//判断是否有带返回参数
{
AlipayNotify aliNotify = new AlipayNotify();
bool verifyResult = aliNotify.Verify(sPara, Request.QueryString["notify_id"], Request.QueryString["sign"]);
if (verifyResult)//验证成功
{
//交易状态:
//WAIT_BUYER_PAY(交易创建,等待买家付款)、
//TRADE_CLOSED(未付款交易超时关闭,或支付完成后全额退款)、
//TRADE_SUCCESS(交易支付成功)、
//TRADE_FINISHED(交易结束,不可退款)
if (trade_status == "TRADE_FINISHED" || trade_status == "TRADE_SUCCESS")
{
string body = Request.QueryString["body"] == null ? "" : Request.QueryString["body"].toString();
string order_id = "";
if (body.Length > 0)
{
AlipayBody bodyClass = JsonConvert.DeserializeObject(body);
order_id = bodyClass.order_id.ToString();
}
Response.Redirect("/StoreAll/OrderInfo.aspx?alireturn_order_id=" + order_id, false);
return;
}
else
{
string trade_msg = trade_status;
if (trade_status == "WAIT_BUYER_PAY")
{
trade_msg = AlipayConfig.WAIT_BUYER_PAY;
}
else if (trade_status == "")
{
trade_msg = AlipayConfig.TRADE_CLOSED;
}
ResponseHtml(trade_msg);
return;
}
}
else//验证失败
{
ZH.SaveErr(new ErrorLog()
{
ErrorId = out_trade_no,
ErrorUser = Config.GardenUser == null ? "" : Config.GardenUser.uname,
ErrorTime = DateTime.Now,
ErrorClass = "return_url.aspx.cs",
ErrorMethod = "Page_Load",
ErrorMsg = "验证失败"
}.toJson());
ResponseHtml("验证失败!");
return;
}
}
else
{
ZH.SaveErr(new ErrorLog()
{
ErrorId = out_trade_no,
ErrorUser = Config.GardenUser == null ? "" : Config.GardenUser.uname,
ErrorTime = DateTime.Now,
ErrorClass = "return_url.aspx.cs",
ErrorMethod = "Page_Load",
ErrorMsg = "无返回参数"
}.toJson());
ResponseHtml("无返回参数!");
return;
}
}
catch (Exception ex)
{
ZH.SaveErr(new ErrorLog()
{
ErrorId = out_trade_no,
ErrorUser = Config.GardenUser == null ? "" : Config.GardenUser.uname,
ErrorTime = DateTime.Now,
ErrorClass = "return_url.aspx.cs",
ErrorMethod = "Page_Load",
ErrorMsg = ex.ToString()
}.toJson());
ResponseHtml("亲,程序开了小差!请联系技术客服!");
return;
}
}
///
/// 获取支付宝GET过来通知消息,并以“参数名=参数值”的形式组成数组
///
/// request回来的信息组成的数组
public SortedDictionary GetRequestGet()
{
int i = 0;
SortedDictionary sArray = new SortedDictionary();
NameValueCollection coll;
coll = Request.QueryString;
String[] requestItem = coll.AllKeys;
for (i = 0; i < requestItem.Length; i++)
{
sArray.Add(requestItem[i], Request.QueryString[requestItem[i]]);
}
return sArray;
}
///
/// 返回前台页面的异常html
///
///
///
public void ResponseHtml(string msg)
{
StringBuilder htmlStr = new StringBuilder();
htmlStr.AppendFormat("");
htmlStr.AppendFormat("支付异常:{0}", msg);
htmlStr.AppendFormat("请点击此处返回订单页面! ");
htmlStr.AppendFormat("
");
Response.Write(htmlStr);
Context.ApplicationInstance.CompleteRequest();
}
}
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Collections.Specialized;
using System.Collections.Generic;
using CS;
using ZhClass;
using Newtonsoft.Json;
using System.Text;
///
/// 功能:服务器异步通知页面
/// 版本:3.3
/// 日期:2012-07-10
/// 说明:
/// 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
/// 该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
/// ///页面功能说明///
/// 创建该页面文件时,请留心该页面文件中无任何HTML代码及空格。
/// 该页面不能在本机电脑测试,请到服务器上做测试。请确保外部可以访问该页面。
/// 该页面调试工具请使用写文本函数logResult。
/// 如果没有收到该页面返回的 success 信息,支付宝会在24小时内按一定的时间策略重发通知
///
//返回的参数列表
//key:discount,value:0.00
//key:payment_type,value:1 --支付类型
//key:trade_no,value:2018071821001004130572785911 --支付宝交易号
//key:subject,value:躺鹰充值 --订单标题/订单名称
//key:buyer_email,value:236*** @qq.com --买家邮件
//key:gmt_create, value:2018-07-18 10:15:27 --交易创建时间
//key:gmt_payment, value:2018-07-18 10:15:49 --交易支付时间
//key:notify_type, value:trade_status_sync --通知类型
//key:quantity, value:1 --购买数量
//key:out_trade_no, value:20180718101532234hCXnMMp4sm --商家交易订单流水号
//key:seller_id, value:2088131525992346 --卖家支付宝账号
//key:notify_time, value:2018-07-18 10:15:49 --通知时间
//key:body, value:139292,10 --订单描述
//key:trade_status, value:TRADE_SUCCESS --订单状态
//key:is_total_fee_adjust, value:N --是否调整总价
//key:total_fee, value:10.00 --订单支付总金额
//key:seller_email, value:[email protected] --买家邮件
//key:price, value:10.00 --商品单价
//key:buyer_id, value:2088902675790131 --买家支付宝账号
//key:notify_id, value:51bb35c52d46a1a7c2f6c8293f77760h09 --通知校验ID
//key:use_coupon, value:N --是否在交易中使用了红包
//key:sign_type, value:MD5 --签名加密类型
//key:sign, value:15b6ff419b5ea89ce3770e37fab1f83b --签名
///
//支付宝承认的返回的result : "fail/success"
public partial class notify_url : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//商户订单号
string out_trade_no = "";
//交易状态
string trade_status = Request.Form["trade_status"] == null ? "" : Request.Form["trade_status"].toString();
ExcuteResult result = new ExcuteResult();
try
{
SortedDictionary sPara = GetRequestPost();
//商户订单号
out_trade_no = Request.Form["out_trade_no"] == null ? "" : Request.Form["out_trade_no"].toString();
if (sPara.Count > 0)//判断是否有带返回参数
{
AlipayNotify aliNotify = new AlipayNotify();
//通过验前,表明是支付宝返回的接口
bool verifyResult = aliNotify.Verify(sPara, Request.Form["notify_id"], Request.Form["sign"]);
if (verifyResult)//验证成功
{
//订单完成
if (trade_status == "TRADE_FINISHED")
{
}
//订单成功
else if (trade_status == "TRADE_SUCCESS")
{
/*
* 1:判断与请求时的 out_trade_no(商家唯一订单号),
* seller_id(收款支付宝账号对应的支付宝唯一用户号),
* total_fee(订单总金额)是否一致
* 2:判断该笔订单在数据库中的合法性
* 3:更新库存
* 4:添加订单状态
* 5;添加日志
*/
//卖家id
string seller_id = Request.Form["seller_id"] == null ? "" : Request.Form["seller_id"].ToString();
//支付宝交易号
string trade_no = Request.Form["trade_no"] == null ? "" : Request.Form["trade_no"].toString();
//订单名称
string subject = Request.Form["subject"] == null ? "" : Request.Form["subject"].toString();
//总金额
decimal total_fee = Request.Form["total_fee"] == null ? Convert.ToDecimal("0.00") : Convert.ToDecimal(Math.Round(Convert.ToDouble(Request.Form["total_fee"].toString()), 2));
//订单描述/detail
string body = Request.Form["body"] == null ? "" : Request.Form["body"].toString();
//订单详情
string order_detail = "";
//订单用户名
string uname = "";
if (body.Length > 0)
{
AlipayBody bodyClass = JsonConvert.DeserializeObject(body);
uname = bodyClass.uname.ToString();
order_detail = bodyClass.order_detail.ToString();
}
//买家id
string buyer_id = Request.Form["buyer_id"] == null ? "" : Request.Form["buyer_id"].ToString();
//交易类型(0:支付宝 1:微信)
int order_pay_type = 0;
//交易支付时间
DateTime gmt_payment = Request.Form["gmt_payment"] == null ? Convert.ToDateTime("1990-01-01") : Convert.ToDateTime(Request.Form["gmt_payment"].ToString());
try
{
#region 记录返回的参数
List str = new List();
for (int i = 0; i < Request.Form.Count; i++)
{
str.Add(string.Format("key:{0},value:{1}", Request.Form.Keys[i], Request.Form[i]));
}
ZH.SaveErr(string.Join("\r\n", str));
#endregion
//判断seller_id(收款支付宝账号对应的支付宝唯一用户号, 以2088开头的纯数字)一致
if (seller_id != AlipayConfig.seller_id)
{
result.Result = false;
result.Msg = "seller_id与请求时不一致!";
ZH.SaveErr(new ErrorLog()
{
ErrorId = out_trade_no,
ErrorUser = Config.GardenUser == null ? "" : Config.GardenUser.uname,
ErrorTime = DateTime.Now,
ErrorClass = "notify_url.aspx.cs",
ErrorMethod = "Page_Load",
ErrorMsg = result.Msg
}.toJson());
//记录异常状态
UpdateErrorStateByReturnSuccessAlipay(uname, out_trade_no, trade_no, subject, seller_id, buyer_id, order_pay_type, total_fee, order_detail, gmt_payment);
Response.Write("fail");
Context.ApplicationInstance.CompleteRequest();
return;
}
//访问数据库,更新库存
var obj = DB.ExeSqlSaving("proc_order_validate_pay", "",
uname, out_trade_no, trade_no, seller_id, buyer_id, order_pay_type, total_fee, order_detail, gmt_payment);
if (obj.Count != 4)
{
result.Result = false;
result.Msg = "存储过程的返回参数数量不对";
ZH.SaveErr(new ErrorLog()
{
ErrorId = out_trade_no,
ErrorUser = Config.GardenUser == null ? "" : Config.GardenUser.uname,
ErrorTime = DateTime.Now,
ErrorClass = "notify_url.aspx.cs",
ErrorMethod = "Page_Load",
ErrorMsg = result.toJson()
}.toJson());
Response.Write("fail");
Context.ApplicationInstance.CompleteRequest();
return;
}
result.Result = obj[1].toString(0) == 0 ? false : true;
result.Msg = obj[2].toString();
//注意:这里需要特别注意 代理商分成的返回,如果代理商分成有错误记录即可,不需要回滚所有订单信息
string order_propor_money_msg = obj[3].ToString();
if (order_propor_money_msg.Trim().Length > 0)
{
result.Msg = order_propor_money_msg;
}
ZH.SaveErr(new ErrorLog()
{
ErrorId = out_trade_no,
ErrorUser = Config.GardenUser == null ? "" : Config.GardenUser.uname,
ErrorTime = DateTime.Now,
ErrorClass = "notify_url.aspx.cs",
ErrorMethod = "Page_Load",
ErrorMsg = result.toJson()
}.toJson());
if (!result.Result)
{
Response.Write("fail");
Context.ApplicationInstance.CompleteRequest();
return;
}
Response.Write("success");
Context.ApplicationInstance.CompleteRequest();
return;
}
catch (Exception ex)
{
result.Result = false;
result.Msg = ex.toString();
ZH.SaveErr(new ErrorLog()
{
ErrorId = out_trade_no,
ErrorUser = Config.GardenUser == null ? "" : Config.GardenUser.uname,
ErrorTime = DateTime.Now,
ErrorClass = "notify_url.aspx.cs",
ErrorMethod = "Page_Load",
ErrorMsg = result.Msg
}.toJson());
//记录异常状态
UpdateErrorStateByReturnSuccessAlipay(uname, out_trade_no, trade_no, subject, seller_id, buyer_id, order_pay_type, total_fee, order_detail, gmt_payment);
Response.Write("fail");
Context.ApplicationInstance.CompleteRequest();
return;
}
}
else
{
result.Result = false;
result.Msg = "支付状态异常:" + trade_status;
ZH.SaveErr(new ErrorLog()
{
ErrorId = out_trade_no,
ErrorUser = Config.GardenUser == null ? "" : Config.GardenUser.uname,
ErrorTime = DateTime.Now,
ErrorClass = "notify_url.aspx.cs",
ErrorMethod = "Page_Load",
ErrorMsg = result.Msg
}.toJson());
Response.Write("fail");
Context.ApplicationInstance.CompleteRequest();
return;
}
}
else//验证失败
{
result.Result = false;
result.Msg = "验证失败";
ZH.SaveErr(new ErrorLog()
{
ErrorId = out_trade_no,
ErrorUser = Config.GardenUser == null ? "" : Config.GardenUser.uname,
ErrorTime = DateTime.Now,
ErrorClass = "notify_url.aspx.cs",
ErrorMethod = "Page_Load",
ErrorMsg = result.Msg
}.toJson());
Response.Write("fail");
Context.ApplicationInstance.CompleteRequest();
return;
}
}
else
{
result.Result = false;
result.Msg = "无通知参数";
ZH.SaveErr(new ErrorLog()
{
ErrorId = out_trade_no,
ErrorUser = Config.GardenUser == null ? "" : Config.GardenUser.uname,
ErrorTime = DateTime.Now,
ErrorClass = "notify_url.aspx.cs",
ErrorMethod = "Page_Load",
ErrorMsg = result.Msg
}.toJson());
Response.Write("fail");
Context.ApplicationInstance.CompleteRequest();
return;
}
}
catch (Exception ex)
{
result.Result = false;
result.Msg = ex.toString();
ZH.SaveErr(new ErrorLog()
{
ErrorId = out_trade_no,
ErrorUser = Config.GardenUser == null ? "" : Config.GardenUser.uname,
ErrorTime = DateTime.Now,
ErrorClass = "notify_url.aspx.cs",
ErrorMethod = "Page_Load",
ErrorMsg = result.Msg
}.toJson());
Response.Write("fail");
Context.ApplicationInstance.CompleteRequest();
return;
}
}
///
/// 获取支付宝POST过来通知消息,并以“参数名=参数值”的形式组成数组
///
/// request回来的信息组成的数组
public SortedDictionary GetRequestPost()
{
int i = 0;
SortedDictionary sArray = new SortedDictionary();
NameValueCollection coll;
coll = Request.Form;
String[] requestItem = coll.AllKeys;
for (i = 0; i < requestItem.Length; i++)
{
sArray.Add(requestItem[i], Request.Form[requestItem[i]]);
}
return sArray;
}
///
/// 支付宝返回支付成功,记录订单异常
///
///
///
///
///
///
///
///
///
///
///
public void UpdateErrorStateByReturnSuccessAlipay(string uname, string order_flow_num, string order_pay_num, string order_subject,
string order_seller_id, string order_buyer_id, int order_pay_type, decimal order_total_amount, string order_memo, DateTime order_pay_time)
{
ExcuteResult result = new ExcuteResult();
var obj = DB.ExeSqlSaving("proc_update_order_state_by_error", "", uname, order_flow_num, order_pay_num, order_subject, order_seller_id, order_buyer_id,
order_pay_type, order_total_amount, order_memo, order_pay_time);
}
}