private Payment FindPayment(string txn_id)
 {
     var paypalHelper = new PaypalHelper();
     var sale = Sale.Get(paypalHelper.GetGetAPIContext(), txn_id);
     var payment = Payment.Get(paypalHelper.GetGetAPIContext(), sale.parent_payment);
     return payment;
 }
        public async Task<ActionResult> PaypalExcecute()
        {
            string payerId = Request.Params["PayerID"];
            var order_id = Request.Params["order_id"];
            var api = GoPlayApi.Instance;
            var transaction = api.GetCoinTransactionByOderId(order_id.ToLower());

            var helper = new PaypalHelper();
            var payment = helper.Find(helper.GetGetAPIContext(), transaction.Data.paypal_payment_id);

            // Rechecks the total amount and currency of PayPal payment
            decimal paypalTotalAmount = Decimal.Parse(payment.transactions[0].amount.total);
            string paypalCurrency = payment.transactions[0].amount.currency;
            if (paypalTotalAmount != transaction.Data.price || paypalCurrency != ConstantCommon.DEFAULT_PAYPAL_CURRENCY)
            {
                transaction.Data.status = "failure";
                transaction.Data.description = "PayPal Error: Invalid currency or total amount.";
                api.UpdateCoinTransactionStatus(transaction.Data.id, transaction.Data.status, transaction.Data.description);

                await api.updateGTokenTransactionStatus(transaction.Data.order_id, "failure");

                return RedirectToAction("index", "transaction");
            }
            var executedPayment = payment.Execute(helper.GetGetAPIContext(), new PaymentExecution() { payer_id = payerId });
            if (executedPayment.state.ToLower() != "approved")
            {
                //when executedPayment is not approved
                //---------------------------------------------
                api.UpdateCoinTransactionStatus(transaction.Data.id, "failure", executedPayment.failed_transactions[0].message);
                await api.updateGTokenTransactionStatus(transaction.Data.order_id, "failure");
                try
                {
                    if (Int32.Parse(executedPayment.failed_transactions[0].code) == 400)
                    {
                        api.UpdateCoinTransactionStatus(transaction.Data.id, "pending");
                    }
                    try
                    {
                        string customerEmail = ConfigurationManager.AppSettings["ADMINS"];//should change
                        string subject = "PlayToken - Topup transaction notification";
                        string from = ConfigurationManager.AppSettings["CUSTOMER_SUPPORT_EMAIL_SENDER"];
                        string to = customerEmail;
                        string body = String.Format("Thank you for your business. Your payment {0} was under review by Paypal service and could take up to 24 hours to release. Once the transaction is completed, the system will update your Play Token automatically.", transaction.Data.paypal_payment_id);

                        var message = new MailMessage(from, to, subject, body);
                        EmailHelper.SendMail(message);
                    }
                    catch (Exception)
                    {
                        string adminEmail = ConfigurationManager.AppSettings["ADMINS"];
                        string subject = "PlayToken wrong email";
                        string from = ConfigurationManager.AppSettings["CUSTOMER_SUPPORT_EMAIL_SENDER"];
                        string to = adminEmail;
                        string body = String.Format("This guy purchased Play Token with a proper email {0} {1} but the payment was under review by Paypal.", CurrentUser.Id, CurrentUser.Email);

                        var message = new MailMessage(from, to, subject, body);
                        EmailHelper.SendMail(message);
                    }

                }
                catch (Exception e)
                {
                    logger.Fatal(e.StackTrace.ToString());

                }

            }
            else
            {
                try
                {
                    //State of transaction is approved
                    //---------------------------------------------
                    transaction.Data.status = "pending";
                    api.UpdateCoinTransactionStatus(transaction.Data.id, transaction.Data.status);
                    //Not use since March 1st 2015
                    //Send a request to Venvici to update their database with the payment
                    //venvici.pushBv(transaction.customerAccount, transaction.amount / 2)
                    try
                    {
                        var invoiceTemplate = new InvoiceViewModel()
                        {
                            transaction = transaction.Data,
                            payer = api.GetUserById(transaction.Data.customer_account_id).Data,
                            package = api.GetGTokenPackage(transaction.Data.gtoken_package_id.Value).Data,
                            topupCard = transaction.Data.topup_card_id.HasValue ? api.GetTopUpCard(transaction.Data.topup_card_id.Value).Data : null
                        };
                        await EmailHelper.SendMailInvoice(invoiceTemplate);

                    }
                    catch (Exception)
                    {
                        string adminEmail = ConfigurationManager.AppSettings["ADMINS"];
                        string subject = "PlayToken wrong email";
                        string from = ConfigurationManager.AppSettings["CUSTOMER_SUPPORT_EMAIL_SENDER"];
                        string to = adminEmail;
                        string body = String.Format("This guy purchased Play Token with a proper email {0} {1}", CurrentUser.Id, CurrentUser.Email);

                        var message = new MailMessage(from, to, subject, body);
                        EmailHelper.SendMail(message);
                    }

                    return RedirectToAction("invoice", "transaction", new { order_id = transaction.Data.order_id });
                }
                catch (Exception ex)
                {
                    api.UpdateCoinTransactionStatus(transaction.Data.id, ex.Message.ToString());
                }
            }
            return RedirectToAction("index", "transaction");
        }
        public async Task<ActionResult> IpnHandler()
        {
            try
            {
                // extract ipn data into a string
                byte[] param = Request.BinaryRead(Request.ContentLength);
                string strRequest = Encoding.ASCII.GetString(param);

                // append PayPal verification code to end of string
                strRequest += "&cmd=_notify-validate";

                logger.Debug(strRequest);

                // create an HttpRequest channel to perform handshake with PayPal
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(ConfigurationManager.AppSettings["PAYPAL_URL"]);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = strRequest.Length;

                // send data back to PayPal to request verification
                StreamWriter streamOut = new StreamWriter(req.GetRequestStream(), Encoding.ASCII);
                streamOut.Write(strRequest);
                streamOut.Close();

                // receive response from PayPal
                StreamReader streamIn = new StreamReader(req.GetResponse().GetResponseStream());
                string strResponse = streamIn.ReadToEnd();
                streamIn.Close();

                // if PayPal response is successful / verified
                logger.Debug(strResponse);
                if (strResponse.Equals("VERIFIED"))
                {
                    // paypal has verified the data, it is safe for us to perform processing now

                    // extract the form fields expected: buyer and seller email, payment status, amount
                    // string payerEmail = Request.Form["payer_email"];
                    string paymentStatus = Request.Form["payment_status"];
                    //string receiverEmail = Request.Form["receiver_email"];
                    string amount = Request.Form["mc_gross"];
                    string txn_id = Request.Form["txn_id"];
                    string txn_type = Request.Form["txn_type"];
                    string payment_type = Request.Form["payment_type"];

                    logger.Debug(txn_id);
                    logger.Debug(txn_type);

                    if (txn_type == "cart" && payment_type == "instant")
                    {
                        if (paymentStatus.Equals("Completed"))
                        {
                            var api = GoPlayApi.Instance;
                            var paypalHelper = new PaypalHelper();
                            var sale = Sale.Get(paypalHelper.GetGetAPIContext(), txn_id);
                            if (sale != null)
                            {
                                var payment_id = sale.parent_payment;
                                var transaction = api.GetCoinTransactionByPaypalPaymentId(payment_id);
                                if (!transaction.HasData)
                                {
                                    return new HttpStatusCodeResult(HttpStatusCode.OK);
                                }


                                var user = api.GetUserById(transaction.Data.customer_account_id).Data;
                                //if transaction.use_gtoken:
                                //# Charge 25% in GToken
                                //gtoken = transaction.amount / 4
                                //sufficientBalance = venvici.checkGToken(user, gtoken)
                                //if not sufficientBalance:
                                //    transaction.status = u'failure'
                                //    transaction.description += u'. Paypal approved but insufficient Play Token'
                                //    store.commit()
                                //    return '', 200
                                //venvici.deductGToken(user, transaction)

                                if (transaction.Data.status == Helper.GetDescription(TransactionStatus.Pending))
                                {
                                    if (user.HasDiscount())
                                    {
                                        user.is_discount_permanent = true;
                                        api.UpdateCustomerAccount(user.id, user.is_discount_permanent);
                                    }
                                    transaction.Data.status = Helper.GetDescription(TransactionStatus.Success);
                                    api.UpdateCoinTransactionStatus(transaction.Data.id, transaction.Data.status);
                                    //update status GTOKEN transaction
                                    await api.updateGTokenTransactionStatus(transaction.Data.order_id, Helper.GetDescription(TransactionStatus.Success));

                                }

                                if (!string.IsNullOrEmpty(user.inviter_username))
                                {
                                    var inviter = api.GetUserByUserName(user.inviter_username);
                                    if (inviter.Data.username == "gdc")
                                    {
                                        string sqlString = @"SELECT * FROM coin_transaction
                                WHERE customer_account_id={0} AND status={1} AND amount >= 5 AND sender_account_id is NULL ";
                                        var transactions = api.GetCoinTransactionsByCustomQuery(String.Format(sqlString, user.id, "success"));
                                        if (transactions.HasData && transactions.Data.Count == 1)
                                        {
                                            var freeCoin = new free_coin_transaction()
                                            {
                                                order_id = Guid.NewGuid().ToString(),
                                                customer_account_id = user.id,
                                                status = Helper.GetDescription(TransactionStatus.Success),
                                                description = "GDC Promotion",
                                                amount = 3
                                            };
                                            api.CreateFreeCoinTransaction(freeCoin);
                                        }
                                    }
                                }
                                //Venici - from 15/3/2015    
                                //venvici.updateVenviciBalance(user,transaction)

                            }
                        }
                    }
                    else
                    {
                        string adminEmail = ConfigurationManager.AppSettings["ADMINS"];
                        string subject = "Another payment type";
                        string body = String.Format("Transaction id: {0}, payment type: {1}, txn type: {2}", txn_id, payment_type, txn_type);
                        var from = new MailAddress("*****@*****.**", "GoPlay Admin");
                        var to = new MailAddress(adminEmail);
                        var message = new MailMessage(from, to)
                        {
                            Subject = subject,
                            Body = body
                        };
                        EmailHelper.SendMail(message);

                    }
                }
            }
            catch (Exception ex)
            {
                logger.Fatal("API Handler: " + ex.StackTrace);
            }

            return new HttpStatusCodeResult(HttpStatusCode.OK);
        }
        public ActionResult Paypal(TransactionPayPal modal)
        {

            var api = GoPlayApi.Instance;
            var package = api.GetTokenPackageBySKU(modal.sku);
            var user = api.GetUserById(CurrentUser.Id);

            string skuItem = package.Data.sku;
            string nameItem = package.Data.name;
            decimal priceItem = package.Data.getPrice(user.Data);
            string currency = ConstantCommon.DEFAULT_PAYPAL_CURRENCY;
            int quantityItem = 1;

            decimal totalAmount = priceItem * quantityItem;
            decimal playTokenAmount = quantityItem * (decimal)package.Data.play_token_amount;

            var coinTransaction = CreateCoinTransactionEntity(package.Data, playTokenAmount, totalAmount);

            coinTransaction = api.CreateCoinTransaction(coinTransaction).Data;

            //For PAYPAL!!!

            var helper = new PaypalHelper();
            var guid = Guid.NewGuid();
            var basePaypalReturn = GetPaypalReturn(guid.ToString());
            var returnUrl = basePaypalReturn + "/paypal_execute?order_id=" + coinTransaction.order_id;
            var cancelUrl = basePaypalReturn + "/cancel?order_id=" + coinTransaction.order_id;

            var itemList = new List<Item>();
            var item = helper.CreateItem(nameItem, currency, priceItem, quantityItem, skuItem);
            itemList.Add(item);

            var amount = helper.CreateAmount(currency, totalAmount);
            var redirectUrls = helper.CreateRedirectUrls(returnUrl, cancelUrl);
            var transactionList = new List<PayPal.Api.Transaction>();
            var transaction = helper.CreateTransaction(coinTransaction.description, amount, itemList);
            transactionList.Add(transaction);
            try
            {
                var createdPayment = helper.CreatePayment(helper.GetGetAPIContext(), transactionList, redirectUrls);
                var links = createdPayment.links.GetEnumerator();
                var paypalRedirectUrl = new PaypalRedirectUrl();

                while (links.MoveNext())
                {
                    Links lnk = links.Current;

                    if (lnk.rel.ToLower().Trim().Equals("approval_url"))
                    {
                        //saving the payapalredirect URL to which user will be redirected for payment
                        paypalRedirectUrl.approval_url = lnk.href;
                    }
                    if (lnk.rel.ToLower().Trim().Equals("execute"))
                    {
                        paypalRedirectUrl.execute = lnk.href;
                    }
                }
                //Save information of transaction into Database
                //State of transaction is pending
                //---------------------------------------------
                coinTransaction.paypal_payment_id = createdPayment.id;
                coinTransaction.paypal_redirect_urls = JsonConvert.SerializeObject(paypalRedirectUrl);

                api.UpdateCoinTransaction(coinTransaction.id, coinTransaction.paypal_redirect_urls, coinTransaction.paypal_payment_id);

                //submit transaction to GTOKEN
                var gtoken_transaction_id = CreateGTokenTransaction(coinTransaction, package.Data, user.Data, totalAmount);

                return Redirect(paypalRedirectUrl.approval_url);
            }
            catch
            {
            }
            //update description
            api.UpdateCoinTransactionStatus(coinTransaction.id, "failure", coinTransaction.description);
            return RedirectToAction("index", "transaction");
        }