Beispiel #1
0
        ///<summary>Replaces variable tags with the information from the patient passed in.</summary>
        public static string ReplaceVarsForSms(string smsTemplate, Patient pat, Statement stmt)
        {
            //No need to check RemotingRole; no call to db.
            StringBuilder retVal = new StringBuilder();

            retVal.Append(smsTemplate);
            if (smsTemplate.Contains("[monthlyCardsOnFile]"))
            {
                retVal.RegReplace("\\[monthlyCardsOnFile]", CreditCards.GetMonthlyCardsOnFile(pat.PatNum));
            }
            retVal.RegReplace("\\[nameF]", pat.GetNameFirst());
            retVal.RegReplace("\\[namePref]", pat.Preferred);
            retVal.RegReplace("\\[PatNum]", pat.PatNum.ToString());
            retVal.RegReplace("\\[currentMonth]", DateTime.Now.ToString("MMMM"));
            Clinic clinic      = Clinics.GetClinic(pat.ClinicNum) ?? Clinics.GetPracticeAsClinicZero();
            string officePhone = clinic.Phone;

            if (string.IsNullOrEmpty(officePhone))
            {
                officePhone = PrefC.GetString(PrefName.PracticePhone);
            }
            retVal.RegReplace("\\[OfficePhone]", TelephoneNumbers.ReFormat(officePhone));
            string officeName = clinic.Description;

            if (string.IsNullOrEmpty(officeName))
            {
                officeName = PrefC.GetString(PrefName.PracticeTitle);
            }
            retVal.RegReplace("\\[OfficeName]", officeName);
            retVal.RegReplace("\\[StatementURL]", stmt.StatementURL);
            retVal.RegReplace("\\[StatementShortURL]", stmt.StatementShortURL);
            return(retVal.ToString());
        }
Beispiel #2
0
 ///<summary>Email statements allow variables to be present in the message body and subject, this method replaces those variables with the information from the patient passed in.  Simply pass in the string for the subject or body and the corresponding patient.</summary>
 private static string ReplaceVarsForEmail(string str, Patient pat)
 {
     //No need to check RemotingRole; no call to db.
     str = str.Replace("[monthlyCardsOnFile]", CreditCards.GetMonthlyCardsOnFile(pat.PatNum));
     str = str.Replace("[nameF]", pat.GetNameFirst());
     str = str.Replace("[nameFL]", pat.GetNameFL());
     str = str.Replace("[nameFLnoPref]", pat.GetNameFLnoPref());
     str = str.Replace("[namePref]", pat.Preferred);
     str = str.Replace("[PatNum]", pat.PatNum.ToString());
     str = str.Replace("[currentMonth]", DateTime.Now.ToString("MMMM"));
     return(str);
 }
Beispiel #3
0
 ///<summary>Throws exceptions.  Will purposefully throw ODExceptions that are already translated and and formatted.
 ///If PatNum is 0, we will make a one time payment for an UNKNOWN patient.  This is currently only intended for prepaid insurance cards.
 ///Returns the PaymentId given by PaySimple.</summary>
 public static ApiResponse MakePayment(long patNum, CreditCard cc, decimal payAmt, string ccNum, DateTime ccExpDate, bool isOneTimePayment, string billingZipCode = "", string cvv = "", long clinicNum = -1)
 {
     ValidateProgram(clinicNum);
     if (patNum == 0)
     {
         //MakePaymentNoPat will validate its credentials.
         return(MakePaymentNoPat(payAmt, ccNum, ccExpDate, billingZipCode, cvv, clinicNum));
     }
     if ((cc == null || string.IsNullOrWhiteSpace(cc.PaySimpleToken)) && (string.IsNullOrWhiteSpace(ccNum) || ccExpDate.Year < DateTime.Today.Year))
     {
         throw new ODException(Lans.g("PaySimple", "Error making payment"));
     }
     if (cc == null)
     {
         cc = new CreditCard()
         {
             PatNum         = patNum,
             PaySimpleToken = "",
         };
     }
     if (string.IsNullOrWhiteSpace(cc.PaySimpleToken))
     {
         Patient patCur = Patients.GetPat(cc.PatNum);
         if (patCur == null)
         {
             patCur = new Patient()
             {
                 PatNum = patNum,
                 FName  = "",
                 LName  = "",
             };
         }
         long        psCustomerId = GetCustomerIdForPat(patCur.PatNum, patCur.FName, patCur.LName, clinicNum);
         ApiResponse apiResponse  = AddCreditCard(psCustomerId, ccNum, ccExpDate, billingZipCode, clinicNum);
         cc.PaySimpleToken = apiResponse.PaySimpleToken;
         if (!isOneTimePayment && cc.CreditCardNum > 0)               //If the user doesn't want Open Dental to store their account id, we will let them continue entering their CC info.
         {
             CreditCards.Update(cc);
         }
     }
     return(PaySimpleApi.PostPayment(GetAuthHeader(clinicNum), PaySimpleApi.MakeNewPaymentData(PIn.Long(cc.PaySimpleToken), payAmt, cvv)));
 }
Beispiel #4
0
        ///<summary>Only deletes the credit card from Open Dental.  We currently do not delete PayConnect tokens from PayConnect anywhere like we do with XCharge/XWeb/PaySimple.
        ///Throws exceptions.</summary>
        public static void DeleteCreditCard(Patient pat, CreditCard cc)
        {
            if (pat == null)
            {
                throw new ODException("No Patient Found", ODException.ErrorCodes.NoPatientFound);
            }
            if (cc == null)
            {
                throw new ODException("No Credit Card Found", ODException.ErrorCodes.OtkArgsInvalid);
            }
            if (string.IsNullOrEmpty(cc.PayConnectToken))
            {
                throw new ODException("Invalid CC Alias", ODException.ErrorCodes.OtkArgsInvalid);
            }
            CreditCards.Delete(cc.CreditCardNum);
            List <CreditCard> creditCards = CreditCards.Refresh(pat.PatNum);

            for (int i = 0; i < creditCards.Count; i++)
            {
                creditCards[i].ItemOrder = creditCards.Count - (i + 1);
                CreditCards.Update(creditCards[i]);                //Resets ItemOrder.
            }
        }
Beispiel #5
0
 public CreditCard ToCreditCard()
 {
     try {
         //This is the class layout for the fields to be pulled out from the successful response string stored in the table
         var responseTypeParial = new {
             CreditCardNumber     = "",
             CreditCardExpireDate = "",
         };
         //Pull out all of the field values we care about from the response string
         var responseValues = JsonConvert.DeserializeAnonymousType(LastResponseStr, responseTypeParial);
         return(new CreditCard()
         {
             PatNum = PatNum,
             PayConnectToken = PaymentToken,
             CCNumberMasked = responseValues.CreditCardNumber,
             CCExpiration = new DateTime(2000 + int.Parse(responseValues.CreditCardExpireDate.Substring(2, 2)), int.Parse(responseValues.CreditCardExpireDate.Substring(0, 2)), 1),            //CCExpDate is stored as MMyy from PayConnect
             CCSource = CCSource,
             ClinicNum = Patients.GetPat(PatNum).ClinicNum,
             ItemOrder = CreditCards.Refresh(PatNum).Count,
             Address = "",
             Zip = "",
             ChargeAmt = 0,
             DateStart = DateTime.MinValue,
             DateStop = DateTime.MinValue,
             Note = "",
             PayPlanNum = 0,
             XChargeToken = "",
             PayConnectTokenExp = new DateTime(2000 + int.Parse(ExpDateToken.Substring(0, 2)), int.Parse(ExpDateToken.Substring(2, 2)), 1),            //ExpDateToken is stored as yyMM
             PaySimpleToken = "",
             Procedures = "",
         });
     }
     catch (Exception e) {
         throw new Exception("Error creating credit card from PayConnect web payment: " + e.Message, e);
     }
 }
Beispiel #6
0
            ///<summary>Returns number of pending transactions remaining after completion.</summary>
            private static int ProcessOutstandingTransactions()
            {
                OnLoggerEvent("Checking for outstanding PaymentTokens.");
                List <PayConnectResponseWeb> listPendingPaymentsAll = PayConnectResponseWebs.GetAllPending();
                //Only process if it's been >= 5 seconds.
                List <PayConnectResponseWeb> listPendingDue = listPendingPaymentsAll.FindAll(x => DateTime.Now.Subtract(x.GetLastPendingUpdateDateTime()) > TimeSpan.FromSeconds(5));

                OnLoggerEvent("Found " + listPendingPaymentsAll.Count + " PaymentTokens. " + listPendingDue.Count.ToString() + " are due to be processed.");
                if (listPendingDue.Count <= 0)                //None are due this time around but we may have some still pending, return count of those.
                {
                    return(listPendingPaymentsAll.Count);
                }
                OnLoggerEvent("Processing " + listPendingDue.Count.ToString() + " outstanding PaymentTokens.", LogLevel.Information);
                //Seed total remaining with any that we won't be processing this time around.
                int remaining = listPendingPaymentsAll.Count - listPendingDue.Count;

                foreach (PayConnectResponseWeb responseWebCur in listPendingDue)
                {
                    try {
                        //This method will update the responseWebCur with all of the data from the /paymentStatus API call
                        PayConnectREST.GetPaymentStatus(responseWebCur);
                        switch (responseWebCur.ProcessingStatus)
                        {
                        case PayConnectWebStatus.Pending:
                            //No new status to report. Try again next time.
                            OnLoggerEvent("PaymentToken still pending: " + responseWebCur.PayToken, LogLevel.Information);
                            if (DateTime.Now.AddMinutes(30) < responseWebCur.GetLastPendingUpdateDateTime())
                            {
                                //Expire this transaction ourselves after 30 minutes.  In testing, PayConnect expires them after 15 minutes.
                                responseWebCur.ProcessingStatus = PayConnectWebStatus.Expired;
                                responseWebCur.DateTimeExpired  = MiscData.GetNowDateTime();
                                OnLoggerEvent("PaymentToken has expired: " + responseWebCur.PayToken, LogLevel.Information);
                            }
                            break;

                        case PayConnectWebStatus.CreatedError:
                        case PayConnectWebStatus.PendingError:
                            OnLoggerEvent("PaymentToken returned an error when retreiving a status update: " + responseWebCur.PayToken, LogLevel.Information);
                            break;

                        case PayConnectWebStatus.Expired:
                            OnLoggerEvent("PaymentToken has expired: " + responseWebCur.PayToken, LogLevel.Information);
                            break;

                        case PayConnectWebStatus.Completed:
                            OnLoggerEvent("PaymentToken has been completed: " + responseWebCur.PayToken, LogLevel.Information);
                            if (responseWebCur.IsTokenSaved)
                            {
                                CreditCards.InsertFromPayConnect(responseWebCur);
                            }
                            Patient pat       = Patients.GetPat(responseWebCur.PatNum);
                            long    clinicNum = 0;
                            if (PrefC.HasClinicsEnabled)
                            {
                                clinicNum = pat.ClinicNum;
                            }
                            string receipt = "";
                            if (!string.IsNullOrWhiteSpace(responseWebCur.LastResponseStr))
                            {
                                var pcInfo = Newtonsoft.Json.JsonConvert.DeserializeAnonymousType(responseWebCur.LastResponseStr,
                                                                                                  new { Amount = (decimal)0.0, CreditCardNumber = "", Messages = new { Message = new string[0] }, RefNumber = "", Status = new { description = "" }, }
                                                                                                  );
                                receipt = BuildReceiptString(PayConnectService.transType.SALE, pcInfo.RefNumber, "", pcInfo.CreditCardNumber, "", "", pcInfo.Status?.description ?? "", pcInfo.Messages.Message.ToList(), pcInfo.Amount, 0, clinicNum);
                            }
                            responseWebCur.PayNum = Payments.InsertFromPayConnect(pat.PatNum, pat.PriProv, clinicNum, responseWebCur.Amount, responseWebCur.GetFormattedNote(true), receipt, responseWebCur.CCSource);
                            break;

                        case PayConnectWebStatus.Cancelled:
                            OnLoggerEvent("PaymentToken has been cancelled: " + responseWebCur.PayToken, LogLevel.Information);
                            break;

                        case PayConnectWebStatus.Declined:
                            OnLoggerEvent("PaymentToken has been declined: " + responseWebCur.PayToken, LogLevel.Information);
                            break;

                        case PayConnectWebStatus.Created:
                        case PayConnectWebStatus.Unknown:
                        case PayConnectWebStatus.UnknownError:
                        default:
                            OnLoggerEvent($"PaymentToken {responseWebCur.PayToken} returned unsupported state: {responseWebCur.ProcessingStatus.ToString()}", LogLevel.Information);
                            break;
                        }
                    }
                    catch (Exception e) {
                        e.DoNothing();
                    }
                    finally {
                        PayConnectResponseWebs.Update(responseWebCur);
                    }
                }
                remaining = listPendingPaymentsAll.FindAll(x => x.ProcessingStatus == PayConnectWebStatus.Pending).Count;
                OnLoggerEvent(remaining.ToString() + " PaymentTokens still pending after processing.", LogLevel.Information);
                return(remaining);
            }