/// <summary> /// Check received signature validity. /// /// Vérification de la signature reçue. /// </summary> /// <param name="values">Received data.</param> /// <param name="shakey">The secret key.</param> /// <returns>True if received signature is the same as computed one.</returns> private bool CheckAuthenticity(NameValueCollection values, string shakey) { // Compute the signature. string computedSign = PaymentUtils.GetSignature(values, shakey); // Check signature consistency. return(String.Equals(values.Get("signature"), computedSign, System.StringComparison.InvariantCultureIgnoreCase)); }
protected void Page_Load(object sender, EventArgs e) { Configuration config = WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath); string shakey = "PRODUCTION".Equals(config.AppSettings.Settings["ctx_mode"].Value) ? // Choose PRODUCTION or TEST SHA key. config.AppSettings.Settings["key_prod"].Value : config.AppSettings.Settings["key_test"].Value; // If vads_hash is present, then the request came from IPN call. if (Request.Form.Get("vads_hash") != null) { // // The order processing will be done here. The return to shop code part should be used only for displaying the payment result to the buyer. // // Le traitement de la commande se fera ici. La partie du code pour le retour à la boutique ne doit servir qu'à l'affichage du résultat pour l'acheteur. // // Check signature consistency. if (CheckAuthenticity(Request.Form, shakey)) { // Use order ID to find the order to update. string orderId = Request.Params.Get("vads_order_id"); // The signature is valid, we can continue processing. PaymentStatus status = PaymentUtils.GetPaymentStatus(Request.Params.Get("vads_trans_status")); if (PaymentStatus.ACCEPTED.Equals(status)) { // Payment accepted. // Insert your logic here to register order, manage stock, empty shopping cart, send e-mail confirmation and more. Response.Write("OK-Accepted payment, order has been updated."); } else if (PaymentStatus.PENDING.Equals(status)) { // Payment is pending. // Insert your logic here to make order in a pending status, empty shopping cart and send notification about order processing. Response.Write("OK-Accepted payment, order has been updated."); } else { // Payment cancelled by the buyer or payment failed. // Insert your logic here to cancel order if already created. Response.Write("OK-Payment failure, order has been cancelled."); } } else { // // The computed signature is not the same as the received one. Potential risk of fraud. The received data should not be used to process order. // // La signature calculée ne correpond pas à la signature reçue. Risque potentiel de fraude. Les données reçues ne doivent pas être prises en compte pour le traitement de la commande. // // Specific error management here. Response.Write("KO-An error occurred while computing the signature."); } } else if (Request.Params.Get("vads_site_id") != null) { // // Return to shop case: We use Request.Params to get received parameters (either return mode is GET or POST). // Note : the siganture validity check is not mandatory on the return to shop because order processing is not done here. // // Cas du retour à la boutique: Nous utilisons Request.Params pour récupérer les paramètres reçus (si le mode de retour est GET ou POST). // Remarque: Il n'est pas obligatoire de calculer la signature sur le retour boutique, le traitement de la commande n'étant pas réalisé ici. // // In test mode, display response parameters. if ("TEST".Equals(Request.Params.Get("vads_ctx_mode"))) { int i = 1; foreach (string key in Request.Params.AllKeys) { if (key == null) { continue; } if (!key.StartsWith("vads_")) { continue; } Label field = (Label)this.FindControl("ctl00$Content$ResultData" + i); field.Text += "[" + key + "=" + Request.Params.Get(key) + "]<br />"; if (i == 2) { i = 1; } else { i++; } } Signature.Text = "[signature=" + Request.Params.Get("signature") + "]"; // In this example, we add this line to display the unhashed signature string in TEST mode. UnhashedSignature.Text = PaymentUtils.GetSignature(Request.Params, shakey, false); } // Check signature consistency. if (CheckAuthenticity(Request.Params, shakey)) { // // Here we check payment result to know which message to show to the buyer. // Ici nous vérifions le résultat du paiement pour déterminer le message à afficher à l'acheteur. // PaymentStatus status = PaymentUtils.GetPaymentStatus(Request.Params.Get("vads_trans_status")); if (PaymentStatus.ACCEPTED.Equals(status)) { // Payment accepted. Insert your code here. ResultMsg.Text = Resources.WebResources.SuccessMsg; } else if (PaymentStatus.PENDING.Equals(status)) { // Payment is pending. Insert your code here. ResultMsg.Text = Resources.WebResources.PendingMsg; } else if (PaymentStatus.CANCELLED.Equals(status)) { // Payment cancelled by buyer. Insert your code here. ResultMsg.Text = Resources.WebResources.CancelMsg; } else { // Payment failed. Insert your code here. ResultMsg.Text = Resources.WebResources.FailureMsg; } } else { // Signature error. Manage error here. ResultMsg.Text = Resources.WebResources.FatalErrorMsg; } } else { // // Client return without parameters (vads_return_mode = NONE). Insert your processing code here. // // Retour navigateur sans paramètres (vads_return_mode = NONE). Inserez votre code de traitement ici. // } }
protected void PayButton_Click(object sender, EventArgs e) { // // Configuration settings such as shop ID and keys are stored in Web.config file. These settings will be available throught the config object below. // // Les paramètres de configuration tels que l'identifiant de la boutique et les clés sont stockés dans le fichier Web.config. Ces paramètres seront accessibles au travers de l'objet config ci-dessous. // Configuration config = WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath); // // Prepare form data to be posted to payment gateway : // - The use of SortedDictionary<key, value> allow sorting data alphabetically to compute signature. // - To add field, use the method SortedDictionary.Add(). // - Keys and values must be strings. // - The data sort order is case insensitive. // // Préparation des données du formulaire à poster à la plateforme de paiement : // - L'utilisation d'un SortedDictionary<clé, valeur> permet d'organiser les données par ordre alphabétique en vue de calculer la signature. // - L'ajout d'un champ se fait avec la méthode SortedDictionary.Add(). // - Les clés et les valeurs stockées doivent être de type string. // - Le tri par ordre alphabétique ne tient pas compte de la casse. // var data = new SortedDictionary <string, string>(StringComparer.InvariantCultureIgnoreCase); // // Mandatory parameters. // data.Add("vads_site_id", config.AppSettings.Settings["shop_id"].Value); // Store identifier. string shakey = "PRODUCTION".Equals(config.AppSettings.Settings["ctx_mode"].Value) ? // Choose PRODUCTION or TEST SHA key. config.AppSettings.Settings["key_prod"].Value : config.AppSettings.Settings["key_test"].Value; // Operating parameters. data.Add("vads_version", "V2"); // Payment form version. V2 is the only possible value. data.Add("vads_contrib", "ASP.NET_Form_Examples_" + PaymentUtils.VERSION); data.Add("vads_ctx_mode", config.AppSettings.Settings["ctx_mode"].Value); // Context mode. data.Add("vads_trans_date", PaymentUtils.GetTransDate()); // Generate UTC payment date in the format expected by the payment gateway : yyyyMMddHHmmss. data.Add("vads_page_action", "PAYMENT"); // This field defines the action executed by the payment gateway. See gateway documentation for more information. data.Add("vads_action_mode", "INTERACTIVE"); // This allows to define the bank data acquisition mode : INTERACTIVE | SILENT. // Payment information. data.Add("vads_currency", "978"); // Currency code in ISO-4217 standard. data.Add("vads_payment_config", "SINGLE"); // Payment type : SINGLE | MULTI | MULTI_EXT. For more information about advanced payment types, please see gateway documentation. // The amount to pay must be expressed in the smallest monetary unit (in cents for euro). var amount = decimal.Parse(Amount.Text.Replace(".", ",")); // Conversion to decimal and replacement of '.' by ','. amount = Convert.ToInt32(amount * 100); // Conversion to cents then to integer to remove the decimal part. data.Add("vads_amount", Convert.ToString(amount)); // Set amount as string. data.Add("vads_trans_id", PaymentUtils.GetTransId()); // Method generating transaction ID based on 1/10 of a second since midnight. // // Optional parameters. // // Payment configuration. data.Add("vads_validation_mode", config.AppSettings.Settings["validation_mode"].Value); data.Add("vads_capture_delay", config.AppSettings.Settings["capture_delay"].Value); data.Add("vads_payment_cards", config.AppSettings.Settings["payment_cards"].Value); // Payment page customization. data.Add("vads_language", (string)Session["language"]); // data.Add("vads_available_languages", ""); // data.Add("vads_shop_name", ""); // data.Add("vads_shop_url", ""); // Return to shop. data.Add("vads_return_mode", "GET"); // GET | POST. data.Add("vads_url_return", ReturnURL()); // data.Add("vads_url_success", ""); // data.Add("vads_url_refused", ""); // data.Add("vads_url_cancel", ""); // data.Add("vads_redirect_success_timeout", ""); // Time in seconds (0-300) before the buyer is automatically redirected to your website after a successful payment. // data.Add("vads_redirect_success_message", ""); // Message displayed on the payment page prior to redirection after a successful payment. // data.Add("vads_redirect_error_timeout", ""); // Time in seconds (0-300) before the buyer is automatically redirected to your website after a declined payment. // data.Add("vads_redirect_error_message", ""); // Message displayed on the payment page prior to redirection after a declined payment. // Information about customer. // data.Add("vads_cust_id", ""); // data.Add("vads_cust_status", ""); // PRIVATE | COMPANY. if (!String.IsNullOrEmpty(Civility.Text)) { data.Add("vads_cust_title", Civility.Text); } // data.Add("vads_cust_name", ""); if (!String.IsNullOrEmpty(FirstName.Text)) { data.Add("vads_cust_first_name", FirstName.Text); } if (!String.IsNullOrEmpty(LastName.Text)) { data.Add("vads_cust_last_name", LastName.Text); } if (!String.IsNullOrEmpty(Address.Text)) { data.Add("vads_cust_address", Address.Text); } // data.Add("vads_cust_number_address", ""); // data.Add("vads_cust_district", ""); if (!String.IsNullOrEmpty(ZipCode.Text)) { data.Add("vads_cust_zip", ZipCode.Text); } if (!String.IsNullOrEmpty(City.Text)) { data.Add("vads_cust_city", City.Text); } // data.Add("vads_cust_state", ""); // data.Add("vads_cust_country", ""); if (!String.IsNullOrEmpty(Phone.Text)) { data.Add("vads_cust_phone", Phone.Text); } // data.Add("vads_cust_cell_phone", ""); if (!String.IsNullOrEmpty(Email.Text)) { data.Add("vads_cust_email", Email.Text); } // Delivery method. // data.Add("vads_ship_to_status", ""); // PRIVATE | COMPANY. // data.Add("vads_ship_to_type", ""); // RECLAIM_IN_SHOP | RELAY_POINT | RECLAIM_IN_STATION | PACKAGE_DELIVERY_COMPANY | ETICKET. // data.Add("vads_ship_to_delivery_company_name", ""); // ex:UPS, La Poste, etc. // data.Add("vads_shipping_amount", ""); // data.Add("vads_tax_amount", ""); // data.Add("vads_insurance_amount", ""); // Delivery address. // data.Add("vads_ship_to_name", ""); // data.Add("vads_ship_to_first_name", ""); // data.Add("vads_ship_to_last_name", ""); // data.Add("vads_ship_to_address_number", ""); // data.Add("vads_ship_to_street", ""); // data.Add("vads_ship_to_street2", ""); // data.Add("vads_ship_to_district", ""); // data.Add("vads_ship_to_zip", ""); // data.Add("vads_ship_to_city", ""); // data.Add("vads_ship_to_state", ""); // data.Add("vads_ship_to_country", ""); // data.Add("vads_ship_to_phone_num", ""); // Order information. if (!String.IsNullOrEmpty(OrderNumber.Text)) { data.Add("vads_order_id", OrderNumber.Text); } // Retrieve order information entered in previous page. // data.Add("vads_order_info", ""); // data.Add("vads_order_info2", ""); // data.Add("vads_order_info3", ""); // Compute signature. data.Add("signature", PaymentUtils.GetSignature(data, shakey)); // Build payment form and redirect to payment gateway. string payForm = PaymentUtils.GetPaymentForm(config.AppSettings.Settings["gateway_url"].Value, data); CheckoutConfirmForm.Parent.Controls.Add(new LiteralControl(payForm)); }