本来支付宝支付不需要服务端提供什么代码的,最多就是存储一些公钥和私钥,但是为了安全,最好还是要在服务端提供支付宝的回调,毕竟客户端是不可相信的。
看了一下支付宝的开发文档,比微信支付的开发文档详细得多,微信开发文档,我竟然没找到服务端的一些demo,我也是醉了。
简单的来讲,支付宝支付分为三步
第一步:拼接参数
biz_content = "{\"timeout_express\":\"30m\",\"product_code\":\"QUICK_MSECURITY_PAY\",\"total_amount\":\"" + Consume.ToString("0.00") + "\",\"subject\":\"" + ConsumeType + "\",\"body\":\"我是支付宝支付\",\"out_trade_no\":\"" + orders.OrderId + "\"}";
//把请求参数打包成数组
Dictionary sParaTemp = new Dictionary();
sParaTemp.Add("app_id", Com.Alipay.Config.App_id); //写在一个类里面,配置文件
sParaTemp.Add("biz_content", biz_content);
sParaTemp.Add("charset", "utf-8");
sParaTemp.Add("method", "alipay.trade.app.pay");
sParaTemp.Add("notify_url", notify_url);
sParaTemp.Add("sign_type", Com.Alipay.Config.Sign_type);
sParaTemp.Add("timestamp", timestamp);
sParaTemp.Add("version", version);
注意total_amount 他的单位是元,并且是精确到分的。还有notify_url一定要是可访问的,不然也会报错,如果是mvc的,就类似这样http://XXXX/KKPay/AliPayNotify ,一般来说,报错最多的还是这一步,要步步小心。
第二步:签名
签名方法如下:
///
/// 生成请求时的签名
///
/// 请求给支付宝的参数数组
/// 签名结果
public static string BuildRequestMysign(Dictionary sPara)
{
//把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
string prestr = Core.CreateLinkString(sPara);
//把最终的字符串签名,获得签名结果
string mysign = "";
switch (_sign_type)
{
case "RSA":
mysign = RSAFromPkcs8.sign(prestr, _private_key, _input_charset);
break;
default:
mysign = "";
break;
}
return mysign;
}
这个方法是获取sign的,得到sign后,把他加到DIctionary里面去
sParaTemp.Add("sign", sign);
第三步:编码
///
/// 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串,并对参数值做urlencode
///
/// 需要拼接的数组
/// 字符编码
/// 拼接完成以后的字符串
public static string CreateLinkStringUrlencode(Dictionary dicArray, Encoding code)
{
StringBuilder prestr = new StringBuilder();
foreach (KeyValuePair temp in dicArray)
{
prestr.Append(temp.Key + "=" + HttpUtility.UrlEncode(temp.Value, code) + "&");
}
//去掉最後一個&字符
int nLen = prestr.Length;
prestr.Remove(nLen - 1, 1);
return prestr.ToString();
}
编码方式UTF-8
这个获得的就是传给支付宝的字符串,把它给客户端童鞋。客户端同学发起支付后,支付宝会往notify_url里面发一个请求。这个请求是post的形式的,他会返回来很多东西,具体是哪些东西可以看支付宝的文档。
我们要写一个接收回调的,他返回来的是支付宝支付是否成功。
首先我们要验证这个消息是不是支付宝发出的合法消息,因为有可能是别人伪装支付宝发出的支付成功的消息,这样,就会造成损失。
///
/// 验证消息是否是支付宝发出的合法消息
///
/// 通知返回参数数组
/// 通知验证ID
/// 支付宝生成的签名结果
/// 验证结果
public bool Verify(SortedDictionary inputPara, string notify_id, string sign)
{
//获取返回时的签名验证结果
bool isSign = GetSignVeryfy(inputPara, sign);
//获取是否是支付宝服务器发来的请求的验证结果
string responseTxt = "true";
if (notify_id != null && notify_id != "") { responseTxt = GetResponseTxt(notify_id); }
//写日志记录(若要调试,请取消下面两行注释)
//string sWord = "responseTxt=" + responseTxt + "\n isSign=" + isSign.ToString() + "\n 返回回来的参数:" + GetPreSignStr(inputPara) + "\n ";
//Core.LogResult(sWord);
//判断responsetTxt是否为true,isSign是否为true
//responsetTxt的结果不是true,与服务器设置问题、合作身份者ID、notify_id一分钟失效有关
//isSign不是true,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关
if (responseTxt == "true" && isSign)//验证成功
{
return true;
}
else//验证失败
{
return false;
}
}
如果验证成功,获取交易的状态
if (Request.Form["trade_status"] == "TRADE_FINISHED")
{
//判断该笔订单是否在商户网站中已经做过处理
//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
//如果有做过处理,不执行商户的业务程序
//注意:
//退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知
}
else if (Request.Form["trade_status"] == "TRADE_SUCCESS")
{
//判断该笔订单是否在商户网站中已经做过处理
//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
//如果有做过处理,不执行商户的业务程序
}
}
如果你的回调地址,没收到请求,支付宝会一直给你发消息,好像是一共发9次还是几次,忘记了,最后处理完,也要给支付宝发一个接收成功的消息,表明我接收到了回调。