.NET WEB API 對接支付寶支付
轉載請注明出處:http://leejunhui.com/2017/02/09/AliPayWithWebAPI/
最近一個項目中需要自己前后臺全棧,幾經權衡之后,在還是選擇了自己最為熟悉的.NET WEB API技術來實現服務器端。可能是由于太久沒接觸.NET了,在對接支付寶APP支付的時候,遇到了不少坑,廢話不多說,直接上代碼吧。
public class AliPayHelper
{
private static string APP_ID = "";
private static string CHARSET = "UTF-8";
/// <summary>
/// 生成RSA簽名后的訂單字符串
/// </summary>
/// <param name="price"></param>
/// <param name="description"></param>
/// <returns></returns>
public static string createRSASignedOrderString(double price,string description)
{
Dictionary<string, string> orderStringDict = new Dictionary<string, string>();
orderStringDict.Add("app_id", APP_ID);
orderStringDict.Add("method", "alipay.trade.app.pay");
orderStringDict.Add("format", "JSON");
orderStringDict.Add("charset", "utf-8");
orderStringDict.Add("sign_type", "RSA");
orderStringDict.Add("timestamp", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
orderStringDict.Add("version", "1.0");
orderStringDict.Add("notify_url", "");
orderStringDict.Add("biz_content", generateBizContentString(price.ToString(), description));
// 排序拼接成字符串
string orderInfo = AlipaySignature.GetSignContent(orderStringDict);
string orderInfoEncoded = Core.CreateLinkStringUrlencode(orderStringDict, (new System.Text.UTF8Encoding()));
// 簽名
string privateKeyPem = GetCurrentPath() + "rsa_private_key.pem";
string signString = AlipaySignature.RSASign(orderInfo, privateKeyPem, null, "RSA");
signString = HttpUtility.UrlEncode(signString, new UTF8Encoding());
// 加上sign
string orderString = orderInfoEncoded + "&sign=" + signString;
// 拼接最終返回給客戶端的字符串
return orderString;
}
static String BytesToBase64(Byte[] bytes)
{
try
{
return Convert.ToBase64String(bytes);
}
catch
{
return null;
}
}
/// <summary>
/// 獲取私鑰的路徑
/// </summary>
/// <returns></returns>
private static string GetCurrentPath()
{
string strPath = "/Helper/";
if (HttpContext.Current != null)
{
return HttpContext.Current.Server.MapPath(strPath);
}
else //非web程序引用
{
strPath = strPath.Replace("/", "\\");
if (strPath.StartsWith("\\"))
{
//strPath = strPath.Substring(strPath.IndexOf('\\', 1)).TrimStart('\\');
strPath = strPath.TrimStart('\\');
}
return System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, strPath);
}
}
/// <summary>
/// 生成業務參數
/// </summary>
/// <param name="price"></param>
/// <param name="descripiton"></param>
/// <returns></returns>
private static string generateBizContentString(string price, string descripiton)
{
Dictionary<string, string> bizContent = new Dictionary<string, string>();
bizContent.Add("subject", descripiton);
bizContent.Add("body", descripiton);
bizContent.Add("out_trade_no", generateOrderNumber());
bizContent.Add("timeout_express", "90m");
bizContent.Add("total_amount", price);
bizContent.Add("product_code", "QUICK_MSECURITY_PAY");
string bizContentJsonString = (new System.Web.Script.Serialization.JavaScriptSerializer()).Serialize(bizContent);
return bizContentJsonString;
}
private static string generateOrderNumber()
{
return DateTime.Now.ToString("yyyyMMddHHmmssfff");
}
}
用法如下:
public async Task<HttpResponseMessage> AliPaySignString(AlipayRequestModel model)
{
var response = new SingleModelResponse<String>() as ISingleModelResponse<String>;
try
{
await Task.Run(() =>
{
string orderString = AliPayHelper.createRSASignedOrderString(Convert.ToDouble(model.price), model.description);
if (null == orderString)
{
response.DidError = true;
response.info = "簽名失敗";
}
else
{
response.Model = orderString;
response.info = "簽名成功";
}
});
}
catch (Exception ex)
{
response.DidError = true;
response.info = ex.InnerException.Message;
}
return response.ToHttpResponse();
}
上面的代碼主要干了一件事情,生成簽名后的訂單字符串返回給app客戶端,然后app客戶端拿著這個字符串去調用支付寶SDK,發起支付請求。為什么要這么麻煩呢?一切都是為了安全,根據支付寶官方開發平臺的解釋,把簽名的過程放在服務器端是要比放在客戶端更為安全的一種策略。
由于網上關于.NET對接支付寶的文章和教程時效性都已經很低了,所以我把項目中的AliPayHelper
代碼放在這,供大家參考。
github代碼地址