|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Objectorg.starhope.appius.util.ManagedReferenceHolder
org.starhope.appius.sql.SQLPeerDatum
org.starhope.appius.mb.Payment
public class Payment
Fairly complete encapsulation of all things related to an individual payment.
Nested Class Summary | |
---|---|
static class |
Payment.ItemType
What type of item is paid-for? Every class implementing Invoiceable should be on this list. |
Field Summary | |
---|---|
private HashMap<String,String> |
annotations
The collection of additional annotations for record-keeping or other purposes. |
private boolean |
closed
Once this is set, no further setting is accepted to any internal fields: the payment record is closed out completely. |
private PaymentCredential |
credentials
The payment credentials presented. |
private Date |
firstTried
The time at which we first tried to post this payment. |
private long |
lastTried
The time at which we last tried to re-submit a pending transaction |
private String |
order_code
The order code is an unique string for this order among all orders placed through a specific source (payment gateway, generally) |
private String |
order_source
The order's source code is an identifier which maps to the payment gateway class, but is user-visible as a part of the total payment identifier (source, code, and sequence number) |
private BigDecimal |
paid
The amount actually paid with this payment. |
private String |
payer
The identification of the payer |
private String |
payment_for
|
private PaymentGatewayReal |
paymentGateway
Through what payment gateway was this payment processed? |
private BigDecimal |
price
The price paid in this payment |
private String |
resultReason
The reason for the failure (if it failed), or the authorization code for the success (if it succeeded) |
private int |
sequence
The sequence number indicates a series of payments that are related to the same event; this is (always, right now, but) typically a subscription recurring every month. |
private Timestamp |
stamp
The moment in time at which, per our accounting, this payment took place. |
private boolean |
success
Was the payment a success? We keep records of failed payments, too, so it's important to ask that question. |
private boolean |
testMode
Was this a test transaction, submitted by the system? It's possible. |
private BigDecimal |
transactionCode
The transaction code returned by the payment gateway |
private UserEnrolment |
userEnrolment
If this payment was made for an enrolment subscription (right now (TODO) they all are), then this stores the pointer to the UserEnrolment record in question. |
private boolean |
verified
|
Constructor Summary | |
---|---|
Payment(Class<AuthorizeNetGateway> gatewayClass,
HashMap<String,String> authorizeNetData)
Handle Silent Post data returned by Authorize.Net. |
|
Payment(ResultSet resultSet)
Instantiate a Payment from the results returned by an SQL statement. |
|
Payment(String orderSourceID,
String orderCodeString,
int paymentSequenceNumber)
Instantiate a Payment for a given order and sequence number. |
|
Payment(UserEnrolment subscription)
|
Method Summary | |
---|---|
void |
addAnnotation(String key,
String value)
WRITEME: document this method (brpocock, Jul 13, 2009) |
private void |
assertClosing()
|
private void |
assertOpen()
|
void |
close()
Close out the payment completely. |
void |
flush()
|
String |
getAnnotation(String key)
WRITEME: document this method (brpocock, Jul 15, 2009) |
protected String |
getCacheUniqueID()
This is an overriding method. |
PaymentCredential |
getCredentials()
Note: Credentials for payment are not saved to JSON or database. |
Currency |
getCurrency()
Get the currency with which this payment was/will be made |
BigDecimal |
getGatewayTransactionCode()
|
static Payment |
getLastPaymentFor(UserEnrolment userEnrolment)
Find the last/latest payment made on a specific enrolment |
BigDecimal |
getPaid()
|
String |
getPayer()
|
String |
getPayment_for()
|
PaymentGateway |
getPaymentGateway()
|
BigDecimal |
getPrice()
|
Payment |
getPriorPayment()
|
String |
getResultReason()
|
Date |
getRetryTime()
If this payment is pending, and we're holding credentials in core, we need to figure out how long before we try again. |
int |
getSequence()
|
Date |
getStamp()
|
Payment |
getStatusFromGateway()
FIXME ... |
UserEnrolment |
getUserEnrolment()
|
private void |
init(String orderSourceID,
String orderCodeString,
int paymentSequenceNumber)
|
boolean |
isClosed()
|
boolean |
isCompleted()
|
boolean |
isSuccess()
|
boolean |
isTest()
|
boolean |
isVerified()
|
void |
prepareForRetry(RetryPaymentException retryPaymentException)
If a payment should retry processing in future (e.g. |
protected void |
set(ResultSet rs)
|
void |
setCredentials(PaymentCredential credentials)
|
void |
setGatewayTransactionCode(BigDecimal transactionCodeNumber)
|
void |
setPaid(BigDecimal paid)
|
void |
setPayment_for(String payment_for)
|
void |
setPaymentGateway(PaymentGatewayReal paymentGatewayReal)
|
void |
setPrice(BigDecimal price)
|
void |
setResultReason(String resultReason)
|
void |
setSequence(int sequence)
|
void |
setSuccess(boolean success)
Note: Once this routine has been called, most of the setters in this Payment will refuse to operate. |
void |
setTest(boolean testMode)
|
void |
setVerified(boolean verified)
|
boolean |
shouldRetry()
|
org.json.JSONObject |
toJSON()
Note, we do not save credentials to any kind of stream or storage (JSON, SQL, &c.). |
Methods inherited from class org.starhope.appius.sql.SQLPeerDatum |
---|
changed, findInCache, get, prepare, prepare, saveInCache, set |
Methods inherited from class org.starhope.appius.util.ManagedReferenceHolder |
---|
deref, setRef |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Field Detail |
---|
private final HashMap<String,String> annotations
The collection of additional annotations for record-keeping or other purposes. These are things not used by the system, but which are tracked in case they're useful for human review, auditing, etc.
Annotations are keyed off dotted domain sequences in the same general fashion as Java class names, etc.
private boolean closed
private transient PaymentCredential credentials
private transient Date firstTried
The time at which we first tried to post this payment. If a temporary problem was encountered, we can hold on to it (in core) and retry for a while, until a (configured) timeout has been reached.
This field is not persistent.
private transient long lastTried
private String order_code
private String order_source
private BigDecimal paid
private String payer
private String payment_for
private PaymentGatewayReal paymentGateway
private BigDecimal price
private String resultReason
private int sequence
private Timestamp stamp
private boolean success
private boolean testMode
true
, we shouldn't give out
anything because of it.
private BigDecimal transactionCode
private UserEnrolment userEnrolment
private boolean verified
Constructor Detail |
---|
public Payment(Class<AuthorizeNetGateway> gatewayClass, HashMap<String,String> authorizeNetData)
gatewayClass
- The class responsible for this payment;
should always be AuthorizeNetGateway for now. Provides an
easy hook to make sure we're in the right place, not
processing e.g. PayPal data here.authorizeNetData
- The key:value pairs of the data from
Authorize.Netpublic Payment(ResultSet resultSet) throws SQLException
resultSet
- The SQL ResultSet with the cursor currently on
the row from which this Payment is to be instantiated.
SQLException
- if we can't cooperate with the database.
Note that we initiate a secondary query on the same
connection to obtain annotations, so there is more
happening here than just fetching results from the
existing ResultSet. If, for example, the connection were
closed in between retrieving the ResultSet including this
payment and instantiating it, it would throw some SQL
exceptions related to that failure.public Payment(String orderSourceID, String orderCodeString, int paymentSequenceNumber) throws NotFoundException
orderSourceID
- The payment gateway originating the orderorderCodeString
- The unique order codepaymentSequenceNumber
- The sequence number
NotFoundException
- if the payment cant't be found.public Payment(UserEnrolment subscription) throws NotFoundException
subscription
-
NotFoundException
Method Detail |
---|
public static Payment getLastPaymentFor(UserEnrolment userEnrolment) throws NotFoundException
userEnrolment
- the enrolment (subscription) object
NotFoundException
- if there are no payments madepublic void addAnnotation(String key, String value) throws AlreadyUsedException
key
- The annotation's key (in inverse-dotted notation)value
- The value for this annotation
AlreadyUsedException
- if the annotation existsannotations
private void assertClosing() throws NotFoundException, AlreadyUsedException
NotFoundException
- if the payment hasn't posted
AlreadyUsedException
- if the payment is completely closedprivate void assertOpen() throws AlreadyUsedException
AlreadyUsedException
- if the payment has been postedpublic void close() throws SQLException
setSuccess(boolean)
, the payment enters a state of
“closing out” for post-processing details only to be added to it.
Once this routine is called, the payment is totally frozen.
SQLException
public void flush()
flush
in class SQLPeerDatum
SQLPeerDatum.flush()
public String getAnnotation(String key)
key
- the ID of the annotation
protected String getCacheUniqueID()
getCacheUniqueID
in class SQLPeerDatum
SQLPeerDatum.getCacheUniqueID()
public PaymentCredential getCredentials()
Note: Credentials for payment are not saved to JSON or database. As such, they only persist as long as they're held in-core.
For this reason, we need to hold on to pending payments' references to avoid potential GC. We cannot re-instantiate a non-completed payment from the database.
This is an intentional security precaution.
public Currency getCurrency()
As with many things, this is still hardcoded as USD.
public BigDecimal getGatewayTransactionCode()
public BigDecimal getPaid()
public String getPayer()
public String getPayment_for()
public PaymentGateway getPaymentGateway()
public BigDecimal getPrice()
public Payment getPriorPayment() throws NotFoundException
NotFoundException
- if there wasn't a prior sequence
payment.public String getResultReason()
public Date getRetryTime() throws AlreadyUsedException, DataException
If this payment is pending, and we're holding credentials in core, we need to figure out how long before we try again. In the spirit of exponential back-off, we'll try every 1 minute for the first 10 minutes, then back off to every 5 minutes for the next 50 minutes, after which we'll go to every 15 minutes until it's been 12 hours, after which time, we'll try every hour until the payment record is dropped.
Note that we need to keep a hard reference to this Payment in the timer routine handling re-submissions, because if the Payment record is purged from the cache, we lose the credentials. This is intentional: we don't want to keep credentials lying around, ever.
AlreadyUsedException
- if the payment can't be retried
DataException
- if there are no payment credentials
available for retryingpublic int getSequence()
public Date getStamp()
public Payment getStatusFromGateway()
public UserEnrolment getUserEnrolment()
private void init(String orderSourceID, String orderCodeString, int paymentSequenceNumber) throws NotFoundException
NotFoundException
public boolean isClosed()
closed
public boolean isCompleted()
public boolean isSuccess()
public boolean isTest()
public boolean isVerified()
public void prepareForRetry(RetryPaymentException retryPaymentException) throws AlreadyUsedException, DataException
retryPaymentException
- the exception causing this to be
scheduled for a do-over
DataException
- ...
AlreadyUsedException
- ...protected void set(ResultSet rs)
set
in class SQLPeerDatum
SQLPeerDatum.set(java.sql.ResultSet)
public void setCredentials(PaymentCredential credentials) throws AlreadyUsedException
credentials
- the credentials to set
AlreadyUsedException
- if the payment is closedpublic void setGatewayTransactionCode(BigDecimal transactionCodeNumber) throws AlreadyUsedException
transactionCodeNumber
- the transaction code number returned
by the payment gateway
AlreadyUsedException
- if this payment has already gotten a
transaction numberpublic void setPaid(BigDecimal paid)
paid
- the paid to setpublic void setPayment_for(String payment_for)
payment_for
- the payment_for to setpublic void setPaymentGateway(PaymentGatewayReal paymentGatewayReal) throws AlreadyUsedException
paymentGatewayReal
- Set the payment gateway through which
this payment was made
AlreadyUsedException
- if the payment has already been madepublic void setPrice(BigDecimal price)
price
- the price to setpublic void setResultReason(String resultReason)
resultReason
- the failedReason to setpublic void setSequence(int sequence)
sequence
- the sequence to setpublic void setSuccess(boolean success)
Note: Once this routine has been called, most of
the setters in this Payment will refuse to operate. It will begin
closing-out. Only post-transaction setters will work, and they
will stop working once close()
is called.
This also causes the Payment object to permanently discard the credentials used for payment.
success
- true if the payment succeeded, false otherwise.public void setTest(boolean testMode) throws AlreadyUsedException
testMode
- If true, then this is meant to be a test
transaction, and not a real payment.
AlreadyUsedException
- if this payment has progressed too
far to be marked as a test nowpublic void setVerified(boolean verified)
verified
- the verified to setpublic boolean shouldRetry()
public org.json.JSONObject toJSON()
Note, we do not save credentials to any kind of stream or storage (JSON, SQL, &c.). Likewise, firstTried is useless in future, since it's only useful in concert with credentials for orders that need a retry.
toJSON
in class SQLPeerDatum
org.starhope.appius.util.BaseDatum#toJSON()
|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |