http://www.sufeinet.com/plugin.php?id=keke_group

苏飞论坛

 找回密码
 马上注册

QQ登录

只需一步,快速开始

分布式系统框架(V2.0) 轻松承载百亿数据,千万流量!讨论专区 - 源码下载 - 官方教程

HttpHelper爬虫框架(V2.7-含.netcore) HttpHelper官方出品,爬虫框架讨论区 - 源码下载 - 在线测试和代码生成

HttpHelper爬虫类(V2.0) 开源的爬虫类,支持多种模式和属性 源码 - 代码生成器 - 讨论区 - 教程- 例子

查看: 11443|回复: 1

[接口] c#支付宝当面付(即时到账)接口异步回调详解notify_url

[复制链接]
发表于 2021-6-18 14:59:12 | 显示全部楼层 |阅读模式
支付宝当面付(即时到账)接口异步回调详解notify_url

我先给大家贴一下支付宝的Demo案例

[C#] 纯文本查看 复制代码
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 Com.Alipay;

/// <summary>
/// 功能:服务器异步通知页面
/// 日期:2016-12-28
/// 说明:
/// 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
/// 该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
/// 
/// ///////////////////页面功能说明///////////////////
/// 创建该页面文件时,请留心该页面文件中无任何HTML代码及空格。
/// 该页面不能在本机电脑测试,请到服务器上做测试。请确保外部可以访问该页面。
/// 如果没有收到该页面返回的 success 信息,支付宝会在24小时内按一定的时间策略重发通知
/// </summary>
public partial class notify_url : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        SortedDictionary<string, string> sPara = GetRequestPost();

        if (sPara.Count > 0)//判断是否有带返回参数
        {
            //Notify aliNotify = new Notify();
            Notify aliNotify = new Notify(Config.charset, Config.sign_type, Config.pid, Config.mapiUrl, Config.alipay_public_key);

            //对异步通知进行验签
            bool verifyResult = aliNotify.Verify(sPara, Request.Form["notify_id"], Request.Form["sign"]);
            //对验签结果
            //bool isSign = Aop.Api.Util.AlipaySignature.RSACheckV2(sPara, Config.alipay_public_key ,Config.charset,Config.sign_type,false );

            if (verifyResult && CheckParams()) //验签成功 && 关键业务参数校验成功
            {
                /////////////////////////////////////////////////////////////////////////////////////////////////////////////
                //请在这里加上商户的业务逻辑程序代码


                //——请根据您的业务逻辑来编写程序(以下代码仅作参考)——
                //获取支付宝的通知返回参数,可参考技术文档中服务器异步通知参数列表

                //商户订单号
                string out_trade_no = Request.Form["out_trade_no"];


                //支付宝交易号
                string trade_no = Request.Form["trade_no"];

                //交易状态
                //在支付宝的业务通知中,只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时,才是买家付款成功。
                string trade_status = Request.Form["trade_status"];


                //判断是否在商户网站中已经做过了这次通知返回的处理
                //如果没有做过处理,那么执行商户的业务程序
                //如果有做过处理,那么不执行商户的业务程序

                Response.Write("success");  //请不要修改或删除

                //——请根据您的业务逻辑来编写程序(以上代码仅作参考)——

                /////////////////////////////////////////////////////////////////////////////////////////////////////////////
            }
            else//验证失败
            {
                Response.Write("fail");
            }
        }
        else
        {
            Response.Write("无通知参数");
        }
    }

    /// <summary>
    /// 对支付宝异步通知的关键参数进行校验
    /// </summary>
    /// <returns></returns>
    private bool CheckParams()
    {
        bool ret = true;

        //获得商户订单号out_trade_no
        string out_trade_no = Request.Form["out_trade_no"];
        //TODO 商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,

        //获得支付总金额total_amount
        string total_amount = Request.Form["total_amount"];
        //TODO 判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),

        //获得卖家账号seller_email
        string seller_email = Request.Form["seller_email"];
        //TODO 校验通知中的seller_email(或者seller_id) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id / seller_email)

        //获得调用方的appid;
        //如果是非授权模式,appid是商户的appid;如果是授权模式(token调用),appid是系统商的appid
        string app_id = Request.Form["app_id"];
        //TODO 验证app_id是否是调用方的appid;。

        //验证上述四个参数,完全吻合则返回参数校验成功
        return ret;

    }

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

        return sArray;
    }



}


我们先来看第一个要点验证签名和参数

[C#] 纯文本查看 复制代码
  //Notify aliNotify = new Notify();
            Notify aliNotify = new Notify(Config.charset, Config.sign_type, Config.pid, Config.mapiUrl, Config.alipay_public_key);

            //对异步通知进行验签
            bool verifyResult = aliNotify.Verify(sPara, Request.Form["notify_id"], Request.Form["sign"]);
            //对验签结果
            //bool isSign = Aop.Api.Util.AlipaySignature.RSACheckV2(sPara, Config.alipay_public_key ,Config.charset,Config.sign_type,false );

            if (verifyResult && CheckParams()) //验签成功 && 关键业务参数校验成功
            {

这一步非常关键,为了减少不必要的麻烦和执行,我们必须先验证是合法的请求参数才进行业务逻辑的处理
以上代码大家根据自己的情况进行修改,但有一点就是这个工作必须要做。不要抱有侥幸心里

第二点是 业务逻辑

业务逻辑部分
[C#] 纯文本查看 复制代码
   //——请根据您的业务逻辑来编写程序(以下代码仅作参考)——
                //获取支付宝的通知返回参数,可参考技术文档中服务器异步通知参数列表

                //商户订单号
                string out_trade_no = Request.Form["out_trade_no"];


                //支付宝交易号
                string trade_no = Request.Form["trade_no"];

                //交易状态
                //在支付宝的业务通知中,只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时,才是买家付款成功。
                string trade_status = Request.Form["trade_status"];
这个主要是大家修改订单执行操作的地方,建议使用存储过程来实现,如果有复杂的逻辑建议使用事务

第三点必须注意的是多次请求的问题

[C#] 纯文本查看 复制代码
                //判断是否在商户网站中已经做过了这次通知返回的处理
                //如果没有做过处理,那么执行商户的业务程序
                //如果有做过处理,那么不执行商户的业务程序

一定要验证一下是否是第一次执行,因为这个接口会通知多次,有时候就是你返回正常的数据也会有多次请求的可能性。所以一定要验证,否则你的订单可能会了现重复修改,多次开通的可能性

第四步,给支付宝响应


[C#] 纯文本查看 复制代码
  Response.Write("success");  //请不要修改或删除

                //——请根据您的业务逻辑来编写程序(以上代码仅作参考)——

                /////////////////////////////////////////////////////////////////////////////////////////////////////////////
            }
            else//验证失败
            {
                Response.Write("fail");
            }


成功就返回一个success 失败是fail
这两个不能省,否则会一直请求这个页面



1. 开通SVIP会员,免费下载本站所有源码,不限次数据,不限时间
2. 加官方QQ群,加官方微信群获取更多资源和帮助
3. 找站长苏飞做网站、商城、CRM、小程序、App、爬虫相关、项目外包等点这里
发表于 2021-6-18 16:49:25 | 显示全部楼层
支持下
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 马上注册

本版积分规则

QQ|手机版|小黑屋|手机版|联系我们|关于我们|广告合作|苏飞论坛 ( 豫ICP备18043678号-2)

GMT+8, 2024-11-22 05:22

© 2014-2021

快速回复 返回顶部 返回列表