142 #include <irrxml/irrXML.hpp>
153 int32_t nReturnVal = 0;
170 if (!strcmp(
"initialPayment", xml->getNodeName())) {
173 m_bInitialPayment =
true;
175 const OTString str_date = xml->getAttributeValue(
"date");
176 const OTString str_completed = xml->getAttributeValue(
"dateCompleted");
178 xml->getAttributeValue(
"dateOfLastAttempt");
180 int64_t tDate = str_date.
ToLong();
181 int64_t tDateCompleted = str_completed.
ToLong();
182 int64_t tDateLastAttempt = str_last_attempt.
ToLong();
193 OTString strCompleted(xml->getAttributeValue(
"completed"));
194 m_bInitialPaymentDone = strCompleted.Compare(
"true");
196 otWarn <<
"\n\nInitial Payment. Amount: " << m_lInitialPaymentAmount
197 <<
". Date: " << tDate
198 <<
". Completed Date: " << tDateCompleted
200 " Number of failed attempts: " << m_nNumberInitialFailures
201 <<
". Date of last failed attempt: " << tDateLastAttempt
204 << (m_bInitialPaymentDone ?
"COMPLETED" :
"NOT completed")
209 else if (!strcmp(
"paymentPlan", xml->getNodeName())) {
211 m_bPaymentPlan =
true;
219 xml->getAttributeValue(
"timeBetweenPayments");
220 const OTString str_start = xml->getAttributeValue(
"planStartDate");
221 const OTString str_length = xml->getAttributeValue(
"planLength");
222 const OTString str_last = xml->getAttributeValue(
"dateOfLastPayment");
224 xml->getAttributeValue(
"dateOfLastFailedPayment");
226 int64_t tBetween = str_between.
ToLong();
227 int64_t tStart = str_start.
ToLong();
228 int64_t tLength = str_length.
ToLong();
229 int64_t tLast = str_last.
ToLong();
230 int64_t tLastAttempt = str_last_attempt.
ToLong();
238 otWarn <<
"\n\nPayment Plan. Amount per payment: "
239 << m_lPaymentPlanAmount
240 <<
". Time between payments: " << tBetween
242 " Payment plan Start Date: " << tStart
243 <<
". Length: " << tLength
244 <<
". Maximum No. of Payments: " << m_nMaximumNoPayments
246 " Completed No. of Payments: " << m_nNoPaymentsDone
247 <<
". Failed No. of Payments: " << m_nNoFailedPayments
249 " Date of last payment: " << tLast
250 <<
" Date of last failed payment: " << tLastAttempt
279 "<agreement\n version=\"%s\"\n"
281 " assetTypeID=\"%s\"\n"
282 " senderAcctID=\"%s\"\n"
283 " senderUserID=\"%s\"\n"
284 " recipientAcctID=\"%s\"\n"
285 " recipientUserID=\"%s\"\n"
287 " cancelerUserID=\"%s\"\n"
288 " transactionNum=\"%lld\"\n"
289 " creationDate=\"%" PRId64
"\"\n"
290 " validFrom=\"%" PRId64
"\"\n"
291 " validTo=\"%" PRId64
"\""
294 SENDER_ACCT_ID.Get(), SENDER_USER_ID.Get(), RECIPIENT_ACCT_ID.Get(),
313 "<closingTransactionNumber value=\"%lld\"/>\n\n", lClosingNumber);
325 "<closingRecipientNumber value=\"%lld\"/>\n\n", lClosingNumber);
334 const time64_t& tFailedInitialPaymentDate =
336 const time64_t& tCompletedInitialPaymentDate =
341 " date=\"%" PRId64
"\"\n"
343 " numberOfAttempts=\"%d\"\n"
344 " dateOfLastAttempt=\"%" PRId64
"\"\n"
345 " dateCompleted=\"%" PRId64
"\"\n"
349 nNumberOfFailedAttempts,
359 const int64_t lTimeBetween =
361 const int64_t lPlanStartDate =
363 const int64_t lPlanLength =
365 const int64_t lDateOfLastPayment =
367 const int64_t lDateOfLastFailedPayment =
375 " amountPerPayment=\"%lld\"\n"
376 " timeBetweenPayments=\"%" PRId64
"\"\n"
377 " planStartDate=\"%" PRId64
"\"\n"
378 " planLength=\"%" PRId64
"\"\n"
379 " maxNoPayments=\"%d\"\n"
380 " completedNoPayments=\"%d\"\n"
381 " failedNoPayments=\"%d\"\n"
382 " dateOfLastPayment=\"%" PRId64
"\"\n"
383 " dateOfLastFailedPayment=\"%" PRId64
"\""
385 lAmountPerPayment, lTimeBetween,
386 lPlanStartDate, lPlanLength, nMaxNoPayments,
387 nNoPaymentsComplete, nNoFailedPayments,
388 lDateOfLastPayment, lDateOfLastFailedPayment);
404 "<merchantSignedCopy>\n%s</merchantSignedCopy>\n\n", ascTemp.
Get());
415 m_bInitialPayment =
true;
416 m_bInitialPaymentDone =
false;
437 if ((
nullptr != pPlan) &&
464 otErr <<
"OTPaymentPlan::" << __FUNCTION__
465 <<
": Expected Merchant's signed copy to be inside the "
466 "payment plan, but unable to load.\n";
471 if (!
Compare(theMerchantCopy)) {
472 otOut <<
"OTPaymentPlan::" << __FUNCTION__
473 <<
": Merchant's copy of payment plan isn't equal to Customer's "
483 otErr <<
"OTPaymentPlan::" << __FUNCTION__ <<
": Transaction number "
485 <<
" isn't on sender's issued list, "
486 "OR there weren't enough closing numbers.\n";
492 otErr <<
"OTPaymentPlan::" << __FUNCTION__
493 <<
": Closing transaction number "
495 <<
" isn't on sender's issued list.\n";
501 otErr <<
"OTPaymentPlan::" << __FUNCTION__
502 <<
": Failed verifying: "
503 "Expected opening and closing transaction numbers for "
504 "recipient. (2 total.)\n";
510 otErr <<
"OTPaymentPlan::" << __FUNCTION__
511 <<
": Recipient's Closing transaction number "
513 <<
" isn't on recipient's issued list.\n";
520 otOut <<
"OTPaymentPlan::" << __FUNCTION__
521 <<
": Sender's signature failed to verify.\n";
528 otOut <<
"OTPaymentPlan::" << __FUNCTION__
529 <<
": Recipient's signature failed to verify on "
530 "internal merchant copy of agreement.\n";
543 time64_t tPlanLength, int32_t nMaxPayments)
546 if (lPaymentAmount <= 0) {
547 otErr <<
"Payment Amount less than zero in "
548 "OTPaymentPlan::SetPaymentPlan\n";
585 otErr <<
"Attempt to use negative number for plan length.\n";
592 if (0 > nMaxPayments)
594 otErr <<
"Attempt to use negative number for plan max payments.\n";
603 m_nNoPaymentsDone = 0;
607 m_bPaymentPlan =
true;
614 , m_bProcessingInitialPayment(false)
615 , m_bProcessingPaymentPlan(false)
623 , m_bProcessingInitialPayment(false)
624 , m_bProcessingPaymentPlan(false)
635 :
ot_super(SERVER_ID, ASSET_ID, SENDER_ACCT_ID, SENDER_USER_ID,
636 RECIPIENT_ACCT_ID, RECIPIENT_USER_ID)
637 , m_bProcessingInitialPayment(false)
638 , m_bProcessingPaymentPlan(false)
645 if (m_bInitialPaymentDone)
648 m_bInitialPaymentDone =
true;
670 bool bSuccess =
false;
681 OTString strSenderUserID(SENDER_USER_ID),
682 strRecipientUserID(RECIPIENT_USER_ID), strSourceAcctID(SOURCE_ACCT_ID),
683 strRecipientAcctID(RECIPIENT_ACCT_ID);
689 if (SOURCE_ACCT_ID == RECIPIENT_ACCT_ID) {
691 <<
"Failed to process payment: both account IDs were identical.\n";
707 std::unique_ptr<OTCronItem> pOrigCronItem(
718 OTString strOrigPlan(*pOrigCronItem);
736 bool bSenderNymIsServerNym =
737 ((SENDER_USER_ID == SERVER_USER_ID) ?
true :
false);
738 bool bRecipientNymIsServerNym =
739 ((RECIPIENT_USER_ID == SERVER_USER_ID) ?
true :
false);
744 bool bUsersAreSameNym =
745 ((SENDER_USER_ID == RECIPIENT_USER_ID) ?
true :
false);
751 if (bSenderNymIsServerNym) {
753 pSenderNym = pServerNym;
762 otErr <<
"Failure loading Sender Nym public key in "
763 "OTPaymentPlan::ProcessPayment: " << strNymID <<
"\n";
775 pSenderNym = &theSenderNym;
779 otErr <<
"Failure loading or verifying Sender Nym public key in "
780 "OTPaymentPlan::ProcessPayment: " << strNymID <<
"\n";
787 if (bRecipientNymIsServerNym) {
789 pRecipientNym = pServerNym;
791 else if (bUsersAreSameNym)
794 pRecipientNym = pSenderNym;
801 OTString strNymID(RECIPIENT_USER_ID);
802 otErr <<
"Failure loading Recipient Nym public key in "
803 "OTPaymentPlan::ProcessPayment: " << strNymID <<
"\n";
810 pRecipientNym = &theRecipientNym;
813 OTString strNymID(RECIPIENT_USER_ID);
814 otErr <<
"Failure loading or verifying Recipient Nym public key in "
815 "OTPaymentPlan::ProcessPayment: " << strNymID <<
"\n";
829 if (!pOrigCronItem->VerifySignature(*pSenderNym) ||
830 !pOrigCronItem->VerifySignature(*pRecipientNym)) {
831 otErr <<
"Failed authorization: Payment plan (while attempting to "
856 std::unique_ptr<OTAccount> pSourceAcct(
859 if (
nullptr == pSourceAcct) {
860 otOut <<
"ERROR verifying existence of source account during attempted "
861 "payment plan processing.\n";
866 std::unique_ptr<OTAccount> pRecipientAcct(
869 if (
nullptr == pRecipientAcct) {
870 otOut <<
"ERROR verifying existence of recipient account during "
871 "attempted payment plan processing.\n";
884 if (pSourceAcct->GetAssetTypeID() !=
885 pRecipientAcct->GetAssetTypeID()) {
890 otOut <<
"ERROR - attempted payment between accounts of different "
891 "asset types in OTPaymentPlan::ProcessPayment\n";
901 else if (!pSourceAcct->VerifyOwner(*pSenderNym) ||
902 !pSourceAcct->VerifySignature(*pServerNym)) {
903 otOut <<
"ERROR verifying ownership or signature on source account in "
904 "OTPaymentPlan::ProcessPayment\n";
908 else if (!pRecipientAcct->VerifyOwner(*pRecipientNym) ||
909 !pRecipientAcct->VerifySignature(*pServerNym)) {
910 otOut <<
"ERROR verifying ownership or signature on recipient account "
911 "in OTPaymentPlan::ProcessPayment\n";
929 OTLedger theSenderInbox(SENDER_USER_ID, SOURCE_ACCT_ID, SERVER_ID),
930 theRecipientInbox(RECIPIENT_USER_ID, RECIPIENT_ACCT_ID, SERVER_ID);
934 bool bSuccessLoadingSenderInbox = theSenderInbox.LoadInbox();
935 bool bSuccessLoadingRecipientInbox = theRecipientInbox.
LoadInbox();
939 if (
true == bSuccessLoadingSenderInbox)
940 bSuccessLoadingSenderInbox =
941 theSenderInbox.VerifyAccount(*pServerNym);
943 bSuccessLoadingSenderInbox = theSenderInbox.GenerateLedger(
947 if (
true == bSuccessLoadingRecipientInbox)
948 bSuccessLoadingRecipientInbox =
955 if ((
false == bSuccessLoadingSenderInbox) ||
956 (
false == bSuccessLoadingRecipientInbox)) {
957 otErr << __FUNCTION__
958 <<
": ERROR loading or generating inbox ledger.\n";
962 int64_t lNewTransactionNumber =
967 if (0 == lNewTransactionNumber) {
968 otOut <<
"WARNING: Payment plan is unable to process because "
969 "there are no more transaction numbers available.\n";
976 lNewTransactionNumber);
980 lNewTransactionNumber);
1046 if (pSourceAcct->GetBalance() >= lAmount) {
1049 pSourceAcct->Debit(lAmount);
1050 bool bMoveRecipient =
false;
1055 pRecipientAcct->Credit(lAmount);
1063 if (!bMoveRecipient)
1064 pSourceAcct->Credit(lAmount);
1070 if (!bMoveSender || !bMoveRecipient) {
1071 otErr <<
"Very strange! Funds were available but debit or "
1072 "credit failed while performing payment.\n";
1083 if (
true == bSuccess)
1102 if (m_bProcessingInitialPayment)
1106 otLog3 <<
"Initial payment performed in "
1107 "OTPaymentPlan::ProcessPayment\n";
1109 else if (m_bProcessingPaymentPlan)
1114 otLog3 <<
"Payment plan payment performed in "
1115 "OTPaymentPlan::ProcessPayment\n";
1136 if (m_bProcessingInitialPayment) {
1139 otLog3 <<
"Initial payment failed in "
1140 "OTPaymentPlan::ProcessPayment\n";
1142 else if (m_bProcessingPaymentPlan) {
1145 otLog3 <<
"Payment plan payment failed in "
1146 "OTPaymentPlan::ProcessPayment\n";
1252 pTransSend->
AddItem(*pItemSend);
1253 pTransRecip->
AddItem(*pItemRecip);
1265 theSenderInbox.AddTransaction(*pTransSend);
1270 theSenderInbox.ReleaseSignatures();
1274 theSenderInbox.SignContract(*pServerNym);
1278 theSenderInbox.SaveContract();
1282 pSourceAcct->SaveInbox(theSenderInbox);
1283 pRecipientAcct->SaveInbox(theRecipientInbox);
1296 if (
true == bSuccess) {
1300 pSourceAcct->ReleaseSignatures();
1301 pRecipientAcct->ReleaseSignatures();
1304 pSourceAcct->SignContract(*pServerNym);
1305 pRecipientAcct->SignContract(*pServerNym);
1308 pSourceAcct->SaveContract();
1309 pRecipientAcct->SaveContract();
1314 pSourceAcct->SaveAccount();
1315 pRecipientAcct->SaveAccount();
1334 m_bProcessingInitialPayment =
true;
1336 m_bProcessingInitialPayment =
false;
1430 m_bProcessingPaymentPlan =
true;
1432 m_bProcessingPaymentPlan =
false;
1480 otLog3 <<
"Cron job has expired.\n";
1492 if (
GetCron()->GetTransactionCount() < 1) {
1493 otOut <<
"Failed to process payment: Out of transaction numbers!\n";
1515 otLog3 <<
"Cron: Processing initial payment...\n";
1521 otLog3 <<
"(payment plan): Flagged/Removal: "
1524 <<
" Current time: "
1572 const int64_t nNoPaymentsThatShouldHaveHappenedByNow =
1573 DURATION_SINCE_START /
1593 otWarn <<
"Payment plan has expired by reaching max number of "
1594 "payments allowed.\n";
1605 otWarn <<
"Payment plan has expired by reaching its maximum length "
1610 else if (nNoPaymentsThatShouldHaveHappenedByNow <=
1633 otLog3 <<
"Cron (processing payment plan): Not enough time since "
1634 "last failed payment.\n";
1642 otLog3 <<
"Cron: Processing payment...\n";
1673 otLog3 <<
"OTPaymentPlan::ProcessCron: Removing payment plan from cron "
1691 m_bInitialPayment =
false;
1695 m_tInitialPaymentCompletedDate =
1697 m_lInitialPaymentAmount = 0;
1698 m_bInitialPaymentDone =
false;
1699 m_nNumberInitialFailures = 0;
1700 m_tFailedInitialPaymentDate =
1704 m_bPaymentPlan =
false;
1705 m_lPaymentPlanAmount = 0;
1706 m_tTimeBetweenPayments =
1715 m_nMaximumNoPayments =
1718 m_tDateOfLastPayment =
1723 m_tDateOfLastFailedPayment =
1725 m_nNoFailedPayments = 0;
int32_t GetMaximumNoPayments() const
const time64_t & GetPaymentPlanLength() const
int64_t GetNextTransactionNumber()
void SetAmount(int64_t lAmount)
const time64_t & GetTimeBetweenPayments() const
virtual int32_t ProcessXMLNode(irr::io::IrrXMLReader *&xml)
void SetDateOfLastFailedPayment(const time64_t &tDateOfLast)
static EXPORT OTTransaction * GenerateTransaction(const OTIdentifier &theUserID, const OTIdentifier &theAccountID, const OTIdentifier &theServerID, transactionType theType, int64_t lTransactionNum=0)
void IncrementNoFailedPayments()
void IncrementNoInitialFailures()
EXPORT int32_t GetRecipientCountClosingNumbers() const
int32_t GetNoPaymentsDone() const
bool HasPaymentPlan() const
const OTIdentifier & GetSenderUserID() const
EXPORT int64_t GetRecipientClosingTransactionNoAt(uint32_t nIndex) const
const time64_t & GetLastFailedInitialPaymentDate() const
const time64_t & GetInitialPaymentDate() const
time64_t GetValidTo() const
virtual EXPORT bool VerifyAccount(const OTPseudonym &theNym)
int64_t GetTransactionNum() const
void SetPaymentPlanStartDate(const time64_t &tPlanStartDate)
void ProcessInitialPayment()
int64_t OTTimeGetTimeInterval(time64_t lhs, time64_t rhs)
EXPORT bool SaveContract()
OTString m_strConsideration
int64_t m_lTransactionNum
EXPORT bool VerifyIssuedNum(const OTString &strServerID, const int64_t &lTransNum) const
time64_t OTTimeAddTimeInterval(time64_t lhs, int64_t rhs)
EXPORT int64_t ToLong() const
const OTIdentifier & GetAssetID() const
const int64_t & GetInitialPaymentAmount() const
static EXPORT OTCronItem * LoadCronReceipt(const int64_t &lTransactionNum)
virtual int32_t ProcessXMLNode(irr::io::IrrXMLReader *&xml)
bool IsFlaggedForRemoval() const
EXPORT bool AddTransaction(OTTransaction &theTransaction)
OTLOG_IMPORT OTLogStream otOut
#define OT_TIME_MONTH_IN_SECONDS
virtual EXPORT bool Compare(OTScriptable &rhs) const
#define PLAN_PROCESS_INTERVAL
const OTIdentifier & GetServerID() const
OTLOG_IMPORT OTLogStream otLog3
EXPORT void SetAttachment(const OTString &theStr)
virtual void UpdateContents()
time64_t OTTimeGetTimeFromSeconds(int64_t seconds)
EXPORT bool LoadSignedNymfile(OTPseudonym &SIGNER_NYM)
OTString m_strMerchantSignedCopy
virtual bool CompareAgreement(const OTAgreement &rhs) const
EXPORT void Concatenate(const char *arg,...)
virtual EXPORT ~OTPaymentPlan()
EXPORT bool VerifyCurrentDate()
EXPORT int64_t GetClosingTransactionNoAt(uint32_t nIndex) const
EXPORT bool VerifyPseudonym() const
virtual bool ProcessCron()
static EXPORT OTItem * CreateItemFromTransaction(const OTTransaction &theOwner, OTItem::itemType theType, const OTIdentifier *pDestinationAcctID=nullptr)
EXPORT void ReleaseSignatures()
EXPORT bool Exists() const
EXPORT bool SetPaymentPlan(const int64_t &lPaymentAmount, time64_t tTimeUntilPlanStart=OT_TIME_MONTH_IN_SECONDS, time64_t tBetweenPayments=OT_TIME_MONTH_IN_SECONDS, time64_t tPlanLength=OT_TIME_ZERO, int32_t nMaxPayments=0)
void ProcessPaymentPlan()
bool HasInitialPayment() const
EXPORT void SetIdentifier(const OTIdentifier &theIdentifier)
virtual bool SaveContractWallet(std::ofstream &ofs) const
const OTIdentifier & GetServerID() const
void SetStatus(const OTItem::itemStatus &theVal)
#define OT_TIME_DAY_IN_SECONDS
time64_t GetValidFrom() const
int32_t GetNoInitialFailures() const
EXPORT bool LoadPublicKey()
EXPORT void SetReferenceString(const OTString &theStr)
EXPORT int32_t GetCountClosingNumbers() const
time64_t OTTimeGetCurrentTime()
int32_t GetNoFailedPayments() const
void SetTimeBetweenPayments(const time64_t &tTimeBetween)
void SetMaximumNoPayments(int32_t nMaxNoPayments)
virtual bool ProcessCron()
const time64_t & GetInitialPaymentCompletedDate() const
const time64_t & GetDateOfLastFailedPayment() const
void SetLastFailedInitialPaymentDate(const time64_t &tFailedInitialPaymentDate)
const time64_t & GetPaymentPlanStartDate() const
OTString m_strContractType
static EXPORT OTLedger * GenerateLedger(const OTIdentifier &theUserID, const OTIdentifier &theAcctID, const OTIdentifier &theServerID, ledgerType theType, bool bCreateFile=false)
void Release_PaymentPlan()
virtual bool VerifyAgreement(OTPseudonym &RECIPIENT_NYM, OTPseudonym &SENDER_NYM) const
void SetInitialPaymentCompletedDate(const time64_t &tInitialPaymentDate)
void SetNoFailedPayments(int32_t nNoFailed)
const int64_t & GetProcessInterval() const
void IncrementNoPaymentsDone()
OTStringXML m_xmlUnsigned
EXPORT bool SetInitialPayment(const int64_t &lAmount, time64_t tTimeUntilInitialPayment=OT_TIME_ZERO)
EXPORT bool SaveBoxReceipt(int64_t lLedgerType)
void SetNoInitialFailures(const int32_t &nNoFailures)
OTLOG_IMPORT OTLogStream otWarn
const int64_t & GetPaymentPlanAmount() const
bool SetInitialPaymentDone()
EXPORT const char * Get() const
const time64_t & GetDateOfLastPayment() const
virtual EXPORT bool SignContract(const OTPseudonym &theNym, const OTPasswordData *pPWData=nullptr)
OTLOG_IMPORT OTLogStream otErr
virtual EXPORT int64_t GetOpeningNumber(const OTIdentifier &theNymID) const
EXPORT void SetReferenceToNum(int64_t lTransactionNum)
OTIdentifier * m_pCancelerNymID
virtual bool CompareAgreement(const OTAgreement &rh) const
OTPseudonym * GetServerNym() const
bool IsInitialPaymentDone() const
bool ProcessPayment(const int64_t &lAmount)
EXPORT void GetString(OTString &theStr) const
virtual EXPORT bool VerifySignature(const OTPseudonym &theNym, const OTPasswordData *pPWData=nullptr) const
const OTIdentifier & GetRecipientUserID() const
const OTIdentifier & GetSenderAcctID() const
void SetNoPaymentsDone(int32_t nNoPaymentsDone)
const time64_t & GetLastProcessDate() const
const OTIdentifier & GetRecipientAcctID() const
void SetPaymentPlanAmount(const int64_t &lAmount)
void SetInitialPaymentAmount(const int64_t &lAmount)
int64_t OTTimeGetSecondsFromTime(time64_t time)
EXPORT bool LoadContractFromString(const OTString &theStr)
void SetInitialPaymentDate(const time64_t &tInitialPaymentDate)
void SetPaymentPlanLength(const time64_t &tPlanLength)
static EXPORT OTAccount * LoadExistingAccount(const OTIdentifier &accountId, const OTIdentifier &serverId)
void SetDateOfLastPayment(const time64_t &tDateOfLast)
virtual EXPORT void Release()
void SetProcessInterval(const int64_t &THE_DATE)
EXPORT void AddItem(OTItem &theItem)
const time64_t & GetCreationDate() const
void SetLastProcessDate(const time64_t &THE_DATE)