<commit_before>using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AnlabMvc.Models.Configuration;
using Anlab.Core.Data;
using Anlab.Core.Domain;
using Anlab.Core.Models;
using AnlabMvc.Models.CyberSource;
using AnlabMvc.Models.Order;
using AnlabMvc.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using Serilog;
using Newtonsoft.Json;

namespace AnlabMvc.Controllers
{
    public class PaymentController : ApplicationController
    {
        private readonly ApplicationDbContext _context;
        private readonly IOrderMessageService _orderMessageService;
        private readonly IDataSigningService _dataSigningService;
        private readonly AppSettings _appSettings;
        private readonly CyberSourceSettings _cyberSourceSettings;

        public PaymentController(ApplicationDbContext context, IOrderMessageService orderMessageService, IDataSigningService dataSigningService, IOptions<CyberSourceSettings> cyberSourceSettings, IOptions<AppSettings> appSettings)
        {
            _context = context;
            _orderMessageService = orderMessageService;
            _dataSigningService = dataSigningService;
            _appSettings = appSettings.Value;
            _cyberSourceSettings = cyberSourceSettings.Value;
        }

        public ActionResult Pay(Guid id)
        {
            var order = _context.Orders.Include(i => i.Creator).SingleOrDefault(a => a.ShareIdentifier == id);

            if (order == null)
            {
                return NotFound();
            }

            if (order.Status != OrderStatusCodes.Accepted)
            {
                ErrorMessage = "You cannot Pay until the Order is Accepted."; 
                return RedirectToAction("Index", "Order");
            }

            Dictionary<string, string> dictionary = SetDictionaryValues(order, order.Creator);

            ViewBag.Signature = _dataSigningService.Sign(dictionary);
            ViewBag.PaymentDictionary = dictionary;
            ViewBag.CyberSourceUrl = _appSettings.CyberSourceUrl;

            var model = new OrderReviewModel();
            model.Order = order;
            model.OrderDetails = order.GetOrderDetails();

            return View(model);
        }


        [HttpPost]
        [IgnoreAntiforgeryToken]
        public ActionResult Receipt(ReceiptResponseModel response)
        {
            Log.ForContext("response", response, true).Information("Receipt response received");

            // check signature
            var dictionary = Request.Form.ToDictionary(x => x.Key.ToString(), x => x.Value.ToString());
            if (!_dataSigningService.Check(dictionary, response.Signature))
            {
                Log.Error("Check Signature Failure");
                ErrorMessage = "An error has occurred. Payment not processed. If you experience further problems, contact us.";
                return RedirectToAction("Index", "Home");
            }

            //var test = ProcessPaymentEvent(response, dictionary); //For testing locally, can enable this.
            //_context.SaveChanges();

            var order = _context.Orders.SingleOrDefault(a => a.Id == response.Req_Reference_Number);
            if (order == null)
            {
                Log.Error("Order not found {0}", response.Req_Reference_Number);
                ErrorMessage = "Order for payment not found. Please contact technical support.";
                return NotFound(response.Req_Reference_Number);
            }
            if (order.CreatorId != CurrentUserId)
            {
                ErrorMessage = "You don't have access to this order.";
                return NotFound(response.Req_Reference_Number);
            }

            var responseValid = CheckResponse(response);
            if (!responseValid.IsValid)
            {
                ErrorMessage = ErrorMessage = string.Format("Errors detected: {0}", string.Join(",", responseValid.Errors));<commit_msg>Closes Issue #201<commit_after>using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AnlabMvc.Models.Configuration;
using Anlab.Core.Data;
using Anlab.Core.Domain;
using Anlab.Core.Models;
using AnlabMvc.Models.CyberSource;
using AnlabMvc.Models.Order;
using AnlabMvc.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using Serilog;
using Newtonsoft.Json;

namespace AnlabMvc.Controllers
{
    public class PaymentController : ApplicationController
    {
        private readonly ApplicationDbContext _context;
        private readonly IOrderMessageService _orderMessageService;
        private readonly IDataSigningService _dataSigningService;
        private readonly AppSettings _appSettings;
        private readonly CyberSourceSettings _cyberSourceSettings;

        public PaymentController(ApplicationDbContext context, IOrderMessageService orderMessageService, IDataSigningService dataSigningService, IOptions<CyberSourceSettings> cyberSourceSettings, IOptions<AppSettings> appSettings)
        {
            _context = context;
            _orderMessageService = orderMessageService;
            _dataSigningService = dataSigningService;
            _appSettings = appSettings.Value;
            _cyberSourceSettings = cyberSourceSettings.Value;
        }

        public ActionResult Pay(Guid id)
        {
            var order = _context.Orders.Include(i => i.Creator).SingleOrDefault(a => a.ShareIdentifier == id);

            if (order == null)
            {
                return NotFound();
            }

            if (order.Status != OrderStatusCodes.Accepted)
            {
                ErrorMessage = "You cannot Pay until the Order is Accepted."; 
                return RedirectToAction("Index", "Order");
            }

            Dictionary<string, string> dictionary = SetDictionaryValues(order, order.Creator);

            ViewBag.Signature = _dataSigningService.Sign(dictionary);
            ViewBag.PaymentDictionary = dictionary;
            ViewBag.CyberSourceUrl = _appSettings.CyberSourceUrl;

            var model = new OrderReviewModel();
            model.Order = order;
            model.OrderDetails = order.GetOrderDetails();

            return View(model);
        }


        [HttpPost]
        [IgnoreAntiforgeryToken]
        public ActionResult Receipt(ReceiptResponseModel response)
        {
            Log.ForContext("response", response, true).Information("Receipt response received");

            // check signature
            var dictionary = Request.Form.ToDictionary(x => x.Key.ToString(), x => x.Value.ToString());
            if (!_dataSigningService.Check(dictionary, response.Signature))
            {
                Log.Error("Check Signature Failure");
                ErrorMessage = "An error has occurred. Payment not processed. If you experience further problems, contact us.";
                return RedirectToAction("Index", "Home");
            }

            //var test = ProcessPaymentEvent(response, dictionary); //For testing locally, can enable this.
            //_context.SaveChanges();

            var order = _context.Orders.SingleOrDefault(a => a.Id == response.Req_Reference_Number);
            if (order == null)
            {
                Log.Error("Order not found {0}", response.Req_Reference_Number);
                ErrorMessage = "Order for payment not found. Please contact technical support.";
                return NotFound(response.Req_Reference_Number);
            }
            //Note, don't check who has access as anyone may pay.
            
            var responseValid = CheckResponse(response);
            if (!responseValid.IsValid)
            {
                ErrorMessage = ErrorMessage = string.Format("Errors detected: {0}", string.Join(",", responseValid.Errors));
{'fraction_non_alphanumeric': 0.08397885159227837, 'fraction_numerical': 0.0008606910119267183, 'mean_word_length': 2.5395996518711925, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1357029', 'n_tokens_mistral': 1976, 'n_tokens_neox': 1935, 'n_words': 476}