PDA

View Full Version : آموزش: پياده سازي پرداخت بانك ملي و Verification نهايي همراه با ثبت در ديتابيس



rana-writes
یک شنبه 08 مرداد 1391, 00:45 صبح
سلام دوستان برنامه نويس
من تقريبا دو هفته درگير پياده سازي درگاه دامون بانك ملي بودم كه بالاخره تونستم انجامش بدم
كدها رو ميذارم تا اگر كسي مثل من به مشكل برخورد كرد، بتونه ازش استفاده كنه

اول اينكه حتما حتما اين تاپيك آقاي اليكي رو مطالعه كنين يه منبع خيلي خوب و عاليه

showthread.php?317958 (http://barnamenevis.org/showthread.php?317958)

من با توجه به راهنماييهاي اين تاپيك تونستم پياده سازي كامل رو انجام بدم

براي ارتباط با بانك ملي دو تا صفحه ميخوايم
يه پيج كه اطلاعات رو به بانك ارسال كنيم و بره به صفحه پرداخت بانك(همون صفحه اي كه اطلاعات كارت رو وارد ميكنيم)
و يكي هم بعد از اينكه پرداخت انجام شد، مشتري به سايت ما برگرده و نتيجه پرداختش رو ببينه

ضمن اينكه توي بخش مديريت سايت، بايد تاييد دستي پرداختها و جوابش رو بذاريم كه پشتيبان بانك حتما اين بخش رو تست ميكنه و بعد از تاييد اين قسمته كه MerchantID اصلي رو بهتون ميده

طبق توضيحات بخش ابتدايي تاپيك آقاي اليكي توي صفحه پرداخت بايد يه سري اطلاعات رو به شكل Post به صفحه بانك بفرستيم
اين در شرايطي كه ما نياز داريم اطلاعات رو توي ديتابيس نگهداري كنيم و بايد با كدنويسي Cs كار كنيم يه كمي مشكل ميشه
براي اينكار از كلاس و تابعي كه آقاي alonemm توي اين تاپيك گذاشتن استفاده كردم

showthread.php?350952 (http://barnamenevis.org/showthread.php?350952)

پس ابتدا يه كلاس ايجاد ميكنيم با اين كدها :


using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Net;
using System.Collections.Specialized;
using System.Text;
/// <summary>
/// Summary description for HttpHelper
/// </summary>
public class HttpHelper
{
public HttpHelper()
{
//
// TODO: Add constructor logic here
//
}

private static String PreparePOSTForm(string url, NameValueCollection data)
{
//Set a name for the form
string formID = "PostForm";

//Build the form using the specified data to be posted.
StringBuilder strForm = new StringBuilder();
strForm.Append("<form id=\"" + formID + "\" name=\"" + formID + "\" action=\"" + url + "\" method=\"POST\">");
foreach (string key in data)
{
strForm.Append("<input type=\"hidden\" name=\"" + key + "\" value=\"" + data[key] + "\">");
}
strForm.Append("</form>");

//Build the JavaScript which will do the Posting operation.
StringBuilder strScript = new StringBuilder();
strScript.Append("<script language='javascript'>");
strScript.Append("var v" + formID + " = document." + formID + ";");
strScript.Append("v" + formID + ".submit();");
strScript.Append("</script>");

//Return the form and the script concatenated. (The order is important, Form then JavaScript)
return strForm.ToString() + strScript.ToString();
}


public static void RedirectAndPOST(Page page, string destinationUrl, NameValueCollection data)
{
//Prepare the Posting form
string strForm = PreparePOSTForm(destinationUrl, data);

//Add a literal control the specified page holding the Post Form, this is to submit the Posting form with the request.
page.Controls.Add(new LiteralControl(strForm));
}
}




بعد هم توي صفحه ي پرداختتون،‌ توي رويداد كليك Button اين كدها رو مي نويسين:



string loginID = "TestId";
string transactionKey = "TestTransact";
string amount = LblWholePool.Text;// مبلغيه كه ميخواين پرداخت بشه
string description = "Sample Transaction";
string testMode = "false"; // در حالت تستي بايد اين فيلد true باشه
string currency = "Rial";

string invoice = DateTime.Now.ToString("yyyyMMddhhmmss");

Random random = new Random();
sequence = (random.Next(0, 10000)).ToString();



string timeStamp = ((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds).ToString();

//x_login^x_fp_sequence^x_fp_timestamp^x_amount^x_cu rrency_code
string fingerprint = HMAC_MD5(transactionKey, loginID + "^" + sequence + "^" + timeStamp + "^" + amount + "^" + currency);


// اين رشته رو بايد ايجاد كنين و توي ديتابيس ذخيره كنين،‌ چون براي تاييد نهايي توي بانك، اين بايد به بانك ملي ارسال بشه
string PostData = "x_description=Sample Transaction&x_login=TestId&x_fp_sequence=" + sequence + "&x_fp_timestamp=" + timeStamp + "&x_amount=" + LblWholePool.Text + "&x_currency_code=Rial&x_fp_hash=" + fingerprint;

// ثبت اطلاعات توي ديتابيس با توجه به شيوه كدنويسي خودتون


NameValueCollection data = new NameValueCollection();
data.Add("x_login", loginID);
data.Add("x_amount", amount);
data.Add("x_description", description);
data.Add("x_test_request",testMode);
data.Add("x_invoice_num", invoice);
data.Add("x_fp_sequence", sequence);
data.Add("x_fp_timestamp", timeStamp);
data.Add("x_fp_hash", fingerprint);
data.Add("x_currency_code", currency);

// توجه كنين در حالت تستي، اينجا بايد آدرس تستي صفحه درگاه دامون باشه، من آدرس اصلي رو اينجا //گذاشتم، توي تاپيك آقاي اليكي آدرسهاي تستي و اصلي وجود داره
HttpHelper.RedirectAndPOST(this.Page, "https://damoon.bankmelli-iran.com/DamoonPrePaymentController", data);



يه تابع هم داريم براي hash كردن مقادير كه بايد به صفحه پرداخت اضافه بشه

string HMAC_MD5(string key, string value)
{
// The first two lines take the input values and convert them from strings to Byte arrays
byte[] HMACkey = (new System.Text.ASCIIEncoding()).GetBytes(key);
byte[] HMACdata = (new System.Text.ASCIIEncoding()).GetBytes(value);

// create a HMACMD5 object with the key set
HMACMD5 myhmacMD5 = new HMACMD5(HMACkey);

//calculate the hash (returns a byte array)
byte[] HMAChash = myhmacMD5.ComputeHash(HMACdata);

//loop through the byte array and add append each piece to a string to obtain a hash string
string fingerprint = "";
for (int i = 0; i < HMAChash.Length; i++)
{
fingerprint += HMAChash[i].ToString("x").PadLeft(2, '0');
}

return fingerprint;
}


اين كل كاري بود كه توي صفحه پرداخت براي ارسال اطلاعات به بانك ملي استفاده ميكنيم

حالا توي صفحه بازگشتي، بايد رشته PostData رو كه ذخيره كردم فراخواني كنيم
بهتر اينه كه يه فيلد براي دسترسي بهش داشته باشيم، كه بهتره با Session انجام بشه و با توجه به اون PostData رو فراخواني كنيم.
توجه مي كنيم كه همه ي اين كارها توي رويداد Page_Load صفحه بازگشتي انجام ميشه
حالا اينجا با هر روشي كه خودتون كدنويسي ميكنين، PostData رو از توي ديتابيستون ميخونين و به سايت بانك مي فرستين به اين شكل:



//فراخواني PostDatah از ديتابيس
PostData = Convert.ToString(reader["PayInfo"]);
webClient.Encoding = System.Text.UnicodeEncoding.UTF8;
webClient.Headers["Content-type"] = "application/x-www-form-urlencoded";

//ارسال PostData به بانك ملي(اينجا باز هم من صفحه اصلي رو گذاشتم، توي پرداختهاي تستي بايد آدرس //صفحه تستي رو بذارين. رجوع به تاپيك آقاي اليكي

string bankResponse = webClient.UploadString("https://Damoon.bankmelli-iran.com/DamoonVerificationController?" + PostData, "POST", PostData);

bankResponse = System.Text.RegularExpressions.Regex.Replace(bankR esponse, @"\<(.|\r|\n)*\>", "").Trim();


string x_trans_id = HttpUtility.ParseQueryString(bankResponse).Get("x_trans_id");

string x_response_code = HttpUtility.ParseQueryString(bankResponse).Get("x_response_code");
string x_response_subcode = HttpUtility.ParseQueryString(bankResponse).Get("x_response_subcode");
string x_response_reason_code = HttpUtility.ParseQueryString(bankResponse).Get("x_response_reason_code");
string x_response_reason_text = HttpUtility.ParseQueryString(bankResponse).Get("x_response_reason_text");



string bankResponse كه از بانك برميگرده يه صفحه حاوي كدهاي Html هست كه به روش بالا تگهاي اضافي رو برميداريم و TransID و ResponseCode رو ازش فراخواني ميكنيم
حالا با توجه به عدد ResponseCode در مورد وضعيت تراكنش تصميم گيري ميكنيم و به كاربر پيام مناسب ميديم

توي صفحه ي مديريت براي خودمون هم تراكنشهايي كه ResponseCode اونها يك نيست رو توي يه گريد فراخواني مي ميكنيم و با گذاشتن يه Button توي گريد، عين همين كدهاي بالا رو توش مي نويسيم و شماره TransId بازگشتي و ResponseCode رو نمايش ميديم

و به اين ترتيب درگاه پرداخت ما آماده است
يه پروژه با اين كدها هم توي فايل ضميمه ميذارم

موفق باشين

اين هم فايل ضميمه پروژه
توضيحات لازم رو توي كدها هم نوشتم و كامنت گذاشتم

90397