c# 支付宝新版接口异步通知notify_url、Return_url处理

因为支付宝已经集成了完整的SDK,所以可以使用SDK直接调用API,这里获取SDK源码。

首先我们需要引用支付宝SDK集成 AopSdk.dll,

添加相关引用:

using Aop.Api.Util;

需要用到商户私钥,支付宝公钥,请求地址等公共参数,所以可以新建一个config文件:

public class newalipayconfig  
{  
    public newalipayconfig()  
    {  
        //  
        // TODO: 在此处添加构造函数逻辑  
        //  
    }  
    // 应用ID,您的APPID  
    public static string app_id = "";  
  
    // 支付宝网关  
    public static string gatewayUrl = "https://openapi.alipay.com/gateway.do";  
  
    // 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。    
    public static string alipay_public_key = "";  
                                                 
    // 商户私钥,您的原始格式RSA私钥  
    public static string private_key = "";  
       
    // 签名方式  
    public static string sign_type = "RSA2";  
  
    // 编码格式  
    public static string charset = "UTF-8";  
}  
回调页面验签处理:

string subNumber;
    string total_fee;      //获取总金额

    protected void Page_Load(object sender, EventArgs e)
    {

        Dictionary sArray = GetRequestPost();
        if (sArray.Count != 0)
        {
            string trade_no = Request.Form["trade_no"];//获取返回状态

            bool signVerified = AlipaySignature.RSACheckV1(sArray, newalipayconfig.alipay_public_key, newalipayconfig.charset, newalipayconfig.sign_type, false); //调用SDK验证签名
            if (signVerified)
            {
                // TODO 验签成功后,按照支付结果异步通知中的描述,对支付结果中的业务内容进行二次校验,校验成功后在response中返回success并继续商户自身业务处理,校验失败返回failure
                if (Request.Form["trade_status"] == "TRADE_FINISHED" || Request.Form["trade_status"] == "TRADE_SUCCESS")//   判断支付状态TRADE_FINISHED(文档中有枚举表可以参考)            
                {                 
                     subNumber = Request.Form["out_trade_no"];//商品订单号
              total_fee = Request.Form["total_fee"];
               Response.Write("success");     //返回给支付宝消息,成功
                }
                else
                {
                    Response.Write("fail");
                }
            }
            else
            {
                // TODO 验签失败则记录异常日志,并在response中返回failure.
                Response.Write("fail");
            }
        }

    }

//获取所有参数,存入map中
    public Dictionary GetRequestPost()
    {
        int i = 0;
        Dictionary sArray = new Dictionary();
        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;

    }

异步返回结果的验签

某商户设置的通知地址为https://api.xx.com/receive_notify.htm,对应接收到通知的示例如下:

https://api.xx.com/receive_notify.htm?total_amount=2.00&buyer_id=2088102116773037&body=大乐透2.1&trade_no=2016071921001003030200089909&refund_fee=0.00¬ify_time=2016-07-19 14:10:49&subject=大乐透2.1&sign_type=RSA2&charset=utf-8¬ify_type=trade_status_sync&out_trade_no=0719141034-6418&gmt_close=2016-07-19 14:10:46&gmt_payment=2016-07-19 14:10:47&trade_status=TRADE_SUCCESS&version=1.0&sign=kPbQIjX+xQc8F0/A6/AocELIjhhZnGbcBN6G4MM/HmfWL4ZiHM6fWl5NQhzXJusaklZ1LFuMo+lHQUELAYeugH8LYFvxnNajOvZhuxNFbN2LhF0l/KL8ANtj8oyPM4NN7Qft2kWJTDJUpQOzCzNnV9hDxh5AaT9FPqRS6ZKxnzM=&gmt_create=2016-07-19 14:10:44&app_id=2015102700040153&seller_id=2088102119685838¬ify_id=4a91b7a78a503640467525113fb7d8bg8e

第一步: 在通知返回参数列表中,除去sign、sign_type两个参数外,凡是通知返回回来的参数皆是待验签的参数。

第二步: 将剩下参数进行url_decode, 然后进行字典排序,组成字符串,得到待签名字符串:

body=大乐透2.1&buyer_id=2088102116773037&charset=utf-8&gmt_close=2016-07-19 14:10:46&gmt_payment=2016-07-19 14:10:47¬ify_time=2016-07-19 14:10:49¬ify_type=trade_status_sync&out_trade_no=0719141034-6418&refund_fee=0.00&subject=大乐透2.1&total_amount=2.00&trade_no=2016071921001003030200089909&trade_status=TRADE_SUCCESS&version=1.0

第三步: 将签名参数(sign)使用base64解码为字节码串。

第四步: 使用RSA的验签方法,通过签名字符串、签名参数(经过base64解码)及支付宝公钥验证签名。

第五步:需要严格按照如下描述校验通知数据的正确性。


SDK自带的验证签名方法,字典排序支持得.NET 3.5以上的版本,所以如果使用的是.NET 2.0版本的需要自己处理签名字符串:




    protected void Page_Load(object sender, EventArgs e)
    {

        Dictionary sArray = GetRequestPost();
        if (sArray.Count != 0)
        {
            sArray.Remove("sign");//除去"sign"参数
            sArray.Remove("sign_type");//除去"sign_type"参数
            List> lst = new List>(sArray);
            //倒叙排列:只需要把变量s2 和 s1 互换就行了 例: return s1.Value.CompareTo(s2.Value);
            //进行排序 目前是顺序
            lst.Sort(delegate(KeyValuePair s1, KeyValuePair s2)
            {
                return s2.Value.CompareTo(s1.Value);
            });

            string signContent = string.Empty;
            string sign = Request.Form["sign"];
            foreach (KeyValuePair kvp in lst)
            {
                signContent += kvp.Key + "=" + kvp.Value + "&";
            }
            signContent = signContent.ToString().Substring(0, signContent.Length - 1);


            string publicKeyPem = "";
            string out_trade_no = Request.Form["out_trade_no"];
            string trade_no = Request.Form["trade_no"];

            //调用SDK验签方法
            bool signVerified = AlipaySignature.RSACheckContent(signContent, sign, newalipayconfig.alipay_public_key, newalipayconfig.charset, newalipayconfig.sign_type, false);

            if (signVerified)   //验证支付发过来的消息,签名是否正确
            {

                Response.Write("success");     //返回给支付宝消息,成功

            }
            else
            {
                v_success.Value = "0";
                Response.Write(sign + "
GetRequestPost() { int i = 0; Dictionary sArray = new Dictionary(); NameValueCollection coll; //coll = Request.Form; coll = Request.Form; String[] requestItem = coll.AllKeys; for (i = 0; i < requestItem.Length; i++) { sArray.Add(requestItem[i], Request.Form[requestItem[i]]); } return sArray; }




你可能感兴趣的:(支付宝,c#)