C#【支付宝】网页端支付流程(四)

版权声明: https://blog.csdn.net/liuchang19950703/article/details/81907033

后台配置接入支付宝支付回调:

附上支付宝接口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&timestamp=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

一.后台回调页面:

1.return_url页面后台代码:

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进行调试
/// </summary>
public partial class return_url : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

        //商户订单号
        string out_trade_no = "";
        try
        {
            
            SortedDictionary<string, string> 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<AlipayBody>(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;
        }
    }

    /// <summary>
    /// 获取支付宝GET过来通知消息,并以“参数名=参数值”的形式组成数组
    /// </summary>
    /// <returns>request回来的信息组成的数组</returns>
    public SortedDictionary<string, string> GetRequestGet()
    {
        int i = 0;
        SortedDictionary<string, string> sArray = new SortedDictionary<string, string>();
        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;
    }

    /// <summary>
    /// 返回前台页面的异常html
    /// </summary>
    /// <param name="msg"></param>
    /// <returns></returns>
    public void ResponseHtml(string msg)
    {
        StringBuilder htmlStr = new StringBuilder();
        htmlStr.AppendFormat("<table style='width:500px; height:200px; background-color:#C7EDCC ;border-radius:5px; margin-left:40%; text-align: center'>");
        htmlStr.AppendFormat("<tr><td><span style='color:red; font-weigth:bold; font-size:20px;'>支付异常:{0}</span>", msg);
        htmlStr.AppendFormat("<a href='/StoreAll/AllOrder.aspx'>请点击此处返回订单页面!</a></td></tr>");
        htmlStr.AppendFormat("</table>");
        Response.Write(htmlStr);
        Context.ApplicationInstance.CompleteRequest();
    }

   

}

2.notify_url页面后台代码

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;


/// <summary>
/// 功能:服务器异步通知页面
/// 版本: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     --签名
/// </summary>

//支付宝承认的返回的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<string, string> 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<AlipayBody>(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<string> str = new List<string>();
                            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;
        }
    }


    /// <summary>
    /// 获取支付宝POST过来通知消息,并以“参数名=参数值”的形式组成数组
    /// </summary>
    /// <returns>request回来的信息组成的数组</returns>
    public SortedDictionary<string, string> GetRequestPost()
    {
        int i = 0;
        SortedDictionary<string, string> sArray = new SortedDictionary<string, string>();
        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;
    }


    /// <summary>
    /// 支付宝返回支付成功,记录订单异常
    /// </summary>
    /// <param name="uname"></param>
    /// <param name="order_flow_num"></param>
    /// <param name="order_pay_num"></param>
    /// <param name="order_subject"></param>
    /// <param name="order_seller_id"></param>
    /// <param name="order_buyer_id"></param>
    /// <param name="order_pay_type"></param>
    /// <param name="order_total_amount"></param>
    /// <param name="order_memo"></param>
    /// <param name="order_pay_time"></param>
    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);
    }
}

 

猜你喜欢

转载自blog.csdn.net/liuchang19950703/article/details/81907033
今日推荐