├── .gitignore ├── LICENSE ├── README.md ├── pom.xml ├── src ├── main │ └── java │ │ └── cc │ │ └── protea │ │ └── spreedly │ │ ├── Spreedly.java │ │ ├── SpreedlyException.java │ │ ├── SpreedlyUtil.java │ │ └── model │ │ ├── SpreedlyApiURLs.java │ │ ├── SpreedlyAvsResponse.java │ │ ├── SpreedlyCardType.java │ │ ├── SpreedlyCreditCard.java │ │ ├── SpreedlyCvvResponse.java │ │ ├── SpreedlyGatewayAccount.java │ │ ├── SpreedlyGatewayAccountState.java │ │ ├── SpreedlyGatewayAuthMode.java │ │ ├── SpreedlyGatewayCharacteristics.java │ │ ├── SpreedlyGatewayCredential.java │ │ ├── SpreedlyGatewayPaymentMethod.java │ │ ├── SpreedlyGatewayProvider.java │ │ ├── SpreedlyGatewayRedactResponse.java │ │ ├── SpreedlyMessage.java │ │ ├── SpreedlyPaymentMethod.java │ │ ├── SpreedlyPaymentMethodState.java │ │ ├── SpreedlyPaymentMethodType.java │ │ ├── SpreedlyShippingAddress.java │ │ ├── SpreedlyStorageState.java │ │ ├── SpreedlyTransactionRequest.java │ │ ├── SpreedlyTransactionResponse.java │ │ ├── SpreedlyTransactionResponseDetails.java │ │ ├── SpreedlyTransactionResponseResponse.java │ │ ├── SpreedlyTransactionState.java │ │ ├── SpreedlyTransactionType.java │ │ └── internal │ │ ├── SpreedlyError.java │ │ ├── SpreedlyErrorHash.java │ │ ├── SpreedlyErrorSetting.java │ │ ├── SpreedlyErrors.java │ │ ├── SpreedlyGatewayAccountResponse.java │ │ ├── SpreedlyGatewayAccountUpdate.java │ │ ├── SpreedlyGatewayProviderResponse.java │ │ ├── SpreedlyInternalKeyValuePair.java │ │ ├── SpreedlyInternalKeyValuePairAdapter.java │ │ ├── SpreedlyNestedMapAdapter.java │ │ ├── SpreedlyPaymentMethodCreateRequest.java │ │ ├── SpreedlyPaymentMethodListResponse.java │ │ ├── SpreedlyPaymentMethodUpdate.java │ │ └── SpreedlyTransactionListResponse.java └── test │ ├── java │ └── cc │ │ └── protea │ │ └── spreedly │ │ ├── SpreedlyErrorHandlingTest.java │ │ ├── SpreedlyTest.java │ │ └── model │ │ └── internal │ │ ├── SpreedlyGatewayAccountUpdateTest.java │ │ └── SpreedlyTransactionResponseTest.java │ └── resources │ ├── SpreedlyGatewayAccountUpdate.xml │ ├── SpreedlyTransactionResponse.xml │ └── SpreedlyTransactionResponseError.xml └── target └── test-classes └── SpreedlyTransactionResponse.xml /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # Package Files # 7 | *.jar 8 | *.war 9 | *.ear 10 | 11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 12 | hs_err_pid* 13 | /.classpath 14 | /.project 15 | /target 16 | 17 | /.idea 18 | *.iml 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Richard Stanford 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | spreedly-java 2 | ============= 3 | 4 | ``` 5 | 6 | cc.protea.spreedly 7 | spreedly 8 | 0.9.9 9 | 10 | ``` 11 | 12 | I've attempted to preserve as much as possible of the Spreedly nomenclature, while making this more accessible to folk who spend 13 | a lot more time writing Java code than they do working with the Spreedly team. 14 | 15 | There are no significant external dependencies. The module does depend on a three-class HTTP utility that I had previously 16 | included but is now its own project, but no substantial code will be pulled in. It also depends on JAXB which should be available 17 | on any reasonable server-side project. 18 | 19 | This is not intended to be used in client-side or mobile applications since it depends heavily on your Spreedly apiSecret which should 20 | never leave your own servers and be exposed to the general public. For pure client-side work, I suggest an approach similar to that 21 | used in https://github.com/rjstanford/spreedly to tokenize. 22 | 23 | In general, the only spelling differences are the use of StudlyCaps rather than under_scores. I have taken the liberty of 24 | branching the Spreedly term "gateway" into "gatewayAccount" and "gatewayProvider", which removes a frequent source of confusion 25 | for people newly exposed to the API. A gatewayProvider is a business such as Authorize.Net, and a gatewayAccount is the 26 | entity represented by a gatewayProvider and a set of credentials, such as a M_ID. 27 | 28 | For general usage, create a new Spreedly(environmentKey, apiSecret) - this is threadsafe - and call its top level methods 29 | directly such as spreedly.listGatewayProviders() or spreedly.purchase(transactionRequest); 30 | 31 | Since I assume that you're going to be using this in a much larger project, all Spreedly classes are prefaced with the word 32 | Spreedly to avoid confusion. 33 | 34 | To run the (trivial) tests, simply set the environment variables SPREEDLYCORE_ENVIRONMENT_KEY and SPREEDLYCORE_API_SECRET to appropriate values. 35 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 4.0.0 5 | 6 | cc.protea.spreedly 7 | spreedly 8 | 0.9.9 9 | jar 10 | 11 | spreedly 12 | Java SDK around the Spreedly RESTful API 13 | 14 | https://github.com/rjstanford/spreedly-java 15 | 16 | 17 | https://github.com/rjstanford/spreedly-java/issues 18 | GitHub Issues 19 | 20 | 21 | 22 | 23 | MIT License 24 | http://www.opensource.org/licenses/mit-license.php 25 | repo 26 | 27 | 28 | 29 | 30 | https://github.com/rjstanford/spreedly-java 31 | scm:git:git://github.com/rjstanford/spreedly-java.git 32 | scm:git:git@github.com:rjstanford/spreedly-java.git 33 | 34 | 35 | 36 | 37 | richard@richardstanford.com 38 | Richard Stanford 39 | https://github.com/rjstanford 40 | rjstanford 41 | 42 | 43 | 44 | 45 | 46 | UTF-8 47 | 48 | 49 | 50 | 51 | junit 52 | junit 53 | 4.10 54 | test 55 | 56 | 57 | cc.protea.foundation.http 58 | http 59 | [0.2,) 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | org.apache.maven.plugins 68 | maven-gpg-plugin 69 | 1.5 70 | 71 | 72 | sign-artifacts 73 | verify 74 | 75 | sign 76 | 77 | 78 | 79 | 80 | 81 | org.apache.maven.plugins 82 | maven-source-plugin 83 | 2.2.1 84 | 85 | 86 | attach-sources 87 | 88 | jar-no-fork 89 | 90 | 91 | 92 | 93 | 94 | org.apache.maven.plugins 95 | maven-javadoc-plugin 96 | 2.9.1 97 | 98 | 99 | attach-javadocs 100 | 101 | jar 102 | 103 | 104 | 105 | 106 | 107 | org.sonatype.plugins 108 | nexus-staging-maven-plugin 109 | 1.6.3 110 | true 111 | 112 | ossrh 113 | https://oss.sonatype.org/ 114 | true 115 | 116 | 117 | 118 | maven-assembly-plugin 119 | 2.2 120 | 121 | 122 | jar-with-dependencies 123 | 124 | 125 | 126 | 127 | make-assembly 128 | package 129 | 130 | single 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | org.springframework.build 139 | aws-maven 140 | 5.0.0.RELEASE 141 | 142 | 143 | 144 | 145 | 146 | 147 | ossrh 148 | https://oss.sonatype.org/content/repositories/snapshots 149 | 150 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/Spreedly.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import cc.protea.spreedly.model.SpreedlyCreditCard; 7 | import cc.protea.spreedly.model.SpreedlyGatewayAccount; 8 | import cc.protea.spreedly.model.SpreedlyGatewayProvider; 9 | import cc.protea.spreedly.model.SpreedlyGatewayRedactResponse; 10 | import cc.protea.spreedly.model.SpreedlyPaymentMethod; 11 | import cc.protea.spreedly.model.SpreedlyTransactionRequest; 12 | import cc.protea.spreedly.model.SpreedlyTransactionResponse; 13 | import cc.protea.spreedly.model.internal.SpreedlyGatewayAccountResponse; 14 | import cc.protea.spreedly.model.internal.SpreedlyGatewayAccountUpdate; 15 | import cc.protea.spreedly.model.internal.SpreedlyGatewayProviderResponse; 16 | import cc.protea.spreedly.model.internal.SpreedlyPaymentMethodCreateRequest; 17 | import cc.protea.spreedly.model.internal.SpreedlyPaymentMethodListResponse; 18 | import cc.protea.spreedly.model.internal.SpreedlyPaymentMethodUpdate; 19 | import cc.protea.spreedly.model.internal.SpreedlyTransactionListResponse; 20 | 21 | public class Spreedly { 22 | 23 | private final SpreedlyUtil util; 24 | 25 | public Spreedly(final String environmentKey, final String apiSecret) { 26 | util = new SpreedlyUtil(environmentKey, apiSecret); 27 | } 28 | 29 | // Gateway Providers 30 | 31 | /** 32 | * Retrieves a list of the currently supported payment gateway providers, including the necessary credentials to 33 | * add that type of gateway to an environment. 34 | */ 35 | public List listGatewayProviders() { 36 | SpreedlyGatewayProviderResponse response = util.options("https://core.spreedly.com/v1/gateways.xml", SpreedlyGatewayProviderResponse.class); 37 | return response.gateways; 38 | } 39 | 40 | /** 41 | * Retrieves information about a single gateway provider. 42 | */ 43 | public SpreedlyGatewayProvider getGatewayProvider(final String name) { 44 | for (SpreedlyGatewayProvider provider : listGatewayProviders()) { 45 | if (provider != null && provider.name != null && provider.name.equals(name)) { 46 | return provider; 47 | } 48 | } 49 | return null; 50 | } 51 | 52 | // Gateway Accounts 53 | 54 | /** 55 | * Retrieve a list of all gateway accounts based on the environment supplied for authentication. 56 | */ 57 | public List listGatewayAccounts() { 58 | List list = new ArrayList(); 59 | String lastToken = null; 60 | do { 61 | List page = listGatewayAccounts(lastToken); 62 | if (page.isEmpty()) { 63 | lastToken = null; 64 | } else { 65 | lastToken = page.get(list.size() - 1).token; 66 | list.addAll(page); 67 | } 68 | } while (lastToken != null); 69 | return list; 70 | } 71 | 72 | /** 73 | * Retrieve a list of all gateway accounts based on the environment supplied for authentication. This is a paginated list, 74 | * for the next page pass in the optional sinceToken parameter 75 | * @param sinceToken the last token received in the previous list 76 | */ 77 | public List listGatewayAccounts(final String sinceToken) { 78 | String tokenString = sinceToken == null ? "" : ("?since_token=" + sinceToken.trim()); 79 | String url = "https://core.spreedly.com/v1/gateways.xml" + tokenString; 80 | SpreedlyGatewayAccountResponse response = util.get(url, SpreedlyGatewayAccountResponse.class); 81 | return response.gateways; 82 | } 83 | 84 | /** 85 | * Retrieve a single gateway account. 86 | */ 87 | public SpreedlyGatewayAccount getGatewayAccount(final String token) { 88 | return util.get("https://core.spreedly.com/v1/gateways/" + token + ".xml", SpreedlyGatewayAccount.class); 89 | } 90 | 91 | /** 92 | * This action allows you to change your credentials for a gateway. 93 | */ 94 | public SpreedlyGatewayAccount update(final SpreedlyGatewayAccount account) { 95 | SpreedlyGatewayAccountUpdate simple = new SpreedlyGatewayAccountUpdate(account); 96 | return util.put("https://core.spreedly.com/v1/gateways/" + account.token + ".xml", simple, SpreedlyGatewayAccount.class); 97 | } 98 | 99 | /** 100 | * Adds a gateway account to the authenticated environment. One gateway account is required for each set of merchant account 101 | * credentials. Spreedly stores and protects the credentials to be used to authenticate with gateway accounts for 102 | * transaction processing. 103 | */ 104 | public SpreedlyGatewayAccount create(final SpreedlyGatewayAccount account) { 105 | SpreedlyGatewayAccountUpdate simple = new SpreedlyGatewayAccountUpdate(account); 106 | return util.post("https://core.spreedly.com/v1/gateways.xml", simple, SpreedlyGatewayAccount.class); 107 | } 108 | 109 | /** 110 | * Gateway accounts can't be deleted (since they're permanently associated with any transactions run against them), but the sensitive credential 111 | * information in them can be redacted so that they're inactive. 112 | */ 113 | public SpreedlyGatewayRedactResponse redact(final SpreedlyGatewayAccount account) { 114 | return util.put("https://core.spreedly.com/v1/gateways/" + account.token + "/redact.xml", null, SpreedlyGatewayRedactResponse.class); 115 | } 116 | 117 | /** 118 | * If you create a gateway account using a normal authenticated add gateway api call, the gateway is automatically retained. If a gateway account 119 | * is created using an unauthenticated channel via the Consumer API, it is kept in a cached state until it is retained or 120 | * automatically redacted. This allows your customers to create gateway accounts using their own credentials, but until you retain 121 | * it, it cannot be used and you will not be billed for it. 122 | */ 123 | public SpreedlyGatewayAccount retain(final SpreedlyGatewayAccount account) { 124 | return util.put("https://core.spreedly.com/v1/gateways/" + account.token + "/retain.xml", null, SpreedlyGatewayAccount.class); 125 | } 126 | 127 | // Transactions 128 | 129 | private SpreedlyTransactionResponse gatewayPost(final SpreedlyTransactionRequest request, final String url) { 130 | return util.post("https://core.spreedly.com/v1/gateways/" + request.gatewayAccountToken + "/" + url, request, SpreedlyTransactionResponse.class); 131 | } 132 | 133 | private SpreedlyTransactionResponse transactionPost(final SpreedlyTransactionRequest request, final String url) { 134 | return util.post("https://core.spreedly.com/v1/transactions/" + request.referenceTransactionToken + "/" + url, request, SpreedlyTransactionResponse.class); 135 | } 136 | 137 | /** 138 | * An authorize transaction will present the gateway with the payment method details along with an amount 139 | * and currency code. Depending on the criteria chosen by the gateway, it will decide if the the funds 140 | * will be allowed to be transferred. It does not take funds at that point, a capture transaction is 141 | * required to move the funds. 142 | */ 143 | public SpreedlyTransactionResponse authorize(final SpreedlyTransactionRequest request) { 144 | return gatewayPost(request, "authorize.xml"); 145 | } 146 | 147 | /** 148 | * The general_credit action can add funds to a credit card. This is different than credit which refunds 149 | * money up to the amount that had been taken during a previous transaction. The general_credit action does 150 | * not require a reference transaction. Support for this capability depends on the gateway. 151 | */ 152 | public SpreedlyTransactionResponse generalCredit(final SpreedlyTransactionRequest request) { 153 | return gatewayPost(request, "general_credit.xml"); 154 | } 155 | 156 | /** 157 | * A purchase call immediately takes funds from the payment method (assuming the transaction succeeds). 158 | */ 159 | public SpreedlyTransactionResponse purchase(final SpreedlyTransactionRequest request) { 160 | if (request.referenceTransactionToken != null) { 161 | return purchase(request.referenceTransactionToken, request.amountInCents, request.currencyCode); 162 | } 163 | return gatewayPost(request, "purchase.xml"); 164 | } 165 | 166 | /** 167 | * The store transaction takes a Spreedly payment method and returns a ThirdPartyToken payment method. 168 | * Since tokens are gateway specific, ThirdPartyToken payment methods are locked to the gateway type 169 | * they were created against, and you'll receive an error if you try to use them with the wrong gateway. 170 | */ 171 | public SpreedlyTransactionResponse store(final SpreedlyTransactionRequest request) { 172 | request.attempt3dSecure = null; 173 | return gatewayPost(request, "store.xml"); 174 | } 175 | 176 | /** 177 | * Retrieves a paginated list of all transactions for a gateway. 178 | * @param sinceToken the last token received in the previous list 179 | * @param desc if true, reverse the order to retrieve the most recent first 180 | */ 181 | public List listGatewayAccountTransactions(final String gatewayAccountToken, final String sinceToken, final boolean desc) { 182 | String url = "https://core.spreedly.com/v1/gateways/" + gatewayAccountToken + "/transactions.xml?order=" + 183 | (desc ? "desc" : "asc") + 184 | (sinceToken == null ? "" : "&since_token = " + sinceToken.trim()); 185 | SpreedlyTransactionListResponse r = util.get(url, SpreedlyTransactionListResponse.class); 186 | return r.transactions; 187 | } 188 | 189 | /** 190 | * Ask a gateway if a payment method is in good standing. Use the retain_on_success request parameter to automatically 191 | * retain the card if it's successfully verified. 192 | */ 193 | public SpreedlyTransactionResponse verify(final SpreedlyTransactionRequest request) { 194 | return gatewayPost(request, "verify.xml"); 195 | } 196 | 197 | /** 198 | * A capture will take the funds previously reserved via an authorization. 199 | */ 200 | public SpreedlyTransactionResponse capture(final SpreedlyTransactionRequest request) { 201 | return transactionPost(request, "capture.xml"); 202 | } 203 | 204 | /** 205 | * A credit is like a void, except it actually reverses a charge instead of just canceling a charge that hasn't 206 | * yet been made. It can also be called a refund. 207 | */ 208 | public SpreedlyTransactionResponse credit(final SpreedlyTransactionRequest request) { 209 | return transactionPost(request, "credit.xml"); 210 | } 211 | 212 | /** 213 | * Retrieves a paginated list of all transactions. 214 | * @param sinceToken the last token received in the previous list 215 | * @param desc if true, reverse the order to retrieve the most recent first 216 | */ 217 | public List listTransactions(final String sinceToken, final boolean desc) { 218 | String url = "https://core.spreedly.com/v1/transactions.xml?order=" + 219 | (desc ? "desc" : "asc") + 220 | (sinceToken == null ? "" : "&since_token = " + sinceToken.trim()); 221 | SpreedlyTransactionListResponse r = util.get(url, SpreedlyTransactionListResponse.class); 222 | return r.transactions; 223 | } 224 | 225 | /** 226 | * Execute a reference purchase using the payment method utilized in a previous transaction. 227 | */ 228 | public SpreedlyTransactionResponse purchase(final String referenceTransactionToken, final Integer amountInCents, final String currencyCode) { 229 | final SpreedlyTransactionRequest request = new SpreedlyTransactionRequest(); 230 | request.referenceTransactionToken = referenceTransactionToken; 231 | request.amountInCents = amountInCents; 232 | request.currencyCode = currencyCode; 233 | return transactionPost(request, "purchase.xml"); 234 | } 235 | 236 | /** 237 | * Retrieve a single transaction. 238 | */ 239 | public SpreedlyTransactionResponse getTransaction(final String token) { 240 | return util.get("https://core.spreedly.com/v1/transactions/" + token + ".xml", SpreedlyTransactionResponse.class); 241 | } 242 | 243 | /** 244 | * Retrieve the transcript for a single transaction. 245 | */ 246 | public String getTranscript(final String token) { 247 | return util.get("https://core.spreedly.com/v1/transactions/" + token + "/transcript", String.class); 248 | } 249 | 250 | /** 251 | * Void is used to cancel out authorizations and, with some gateways, to cancel actual payment transactions within the 252 | * first 24 hours (credits are used after that). 253 | */ 254 | public SpreedlyTransactionResponse voidTransaction(final SpreedlyTransactionRequest request) { 255 | return transactionPost(request, "void.xml"); 256 | } 257 | 258 | // Payment Methods 259 | 260 | /** 261 | * This way of adding a payment method requires being authenticated. Therefore you will only add payment methods in this manner 262 | * from your own servers because you will not want to reveal you access secret to your customers. It is important to know that 263 | * transmitting sensitive data through your servers significantly increases your PCI compliance requirements. 264 | */ 265 | public SpreedlyTransactionResponse create(final SpreedlyCreditCard creditCard) { 266 | SpreedlyPaymentMethodCreateRequest request = new SpreedlyPaymentMethodCreateRequest(); 267 | request.creditCard = creditCard; 268 | request.data = creditCard.data; 269 | request.email = creditCard.email; 270 | return util.post("https://core.spreedly.com/v1/payment_methods.xml", request, SpreedlyTransactionResponse.class); 271 | } 272 | 273 | /** 274 | * Retrieve a list of all payment methods based on the environment supplied for authentication. This is a paginated list, 275 | * for the next page pass in the optional sinceToken parameter 276 | * @param sinceToken the last token received in the previous list 277 | */ 278 | public List listPaymentMethods(final String sinceToken, final boolean desc) { 279 | String url = "https://core.spreedly.com/v1/payment_methods.xml?order=" + 280 | (desc ? "desc" : "asc") + 281 | (sinceToken == null ? "" : "&since_token = " + sinceToken.trim()); 282 | SpreedlyPaymentMethodListResponse r = util.get(url, SpreedlyPaymentMethodListResponse.class); 283 | return r.paymentMethods; 284 | } 285 | 286 | /** 287 | * There are some parts of a payment method that Spreedly cannot retain, e.g. the CVV of a credit card. In some cases, 288 | * it may be advantageous to re-supply that information to be used for a transaction that's about to be run. For these 289 | * cases Spreedly provides the ability to re-cache sensitive data for an existing payment method so that you do not 290 | * have to recollect the whole payment method. Only sensitive fields can be re-cached (currently the verificationValue 291 | * for credit cards), and any already vaulted data will be ignored. 292 | */ 293 | public SpreedlyTransactionResponse recache(final String paymentMethodToken, final String verificationValue) { 294 | SpreedlyPaymentMethod request = new SpreedlyPaymentMethod(); 295 | request.verificationValue = verificationValue; 296 | request.token = paymentMethodToken; 297 | return recache(request); 298 | } 299 | 300 | /** 301 | * There are some parts of a payment method that Spreedly cannot retain, e.g. the CVV of a credit card. In some cases, 302 | * it may be advantageous to re-supply that information to be used for a transaction that's about to be run. For these 303 | * cases Spreedly provides the ability to re-cache sensitive data for an existing payment method so that you do not 304 | * have to recollect the whole payment method. Only sensitive fields can be re-cached (currently the verificationValue 305 | * for credit cards), and any already vaulted data will be ignored. 306 | */ 307 | public SpreedlyTransactionResponse recache(final SpreedlyPaymentMethod paymentMethod) { 308 | return util.post("https://core.spreedly.com/v1/payment_methods/" + paymentMethod.token + "/recache.xml", paymentMethod, SpreedlyTransactionResponse.class); 309 | } 310 | 311 | /** 312 | *

313 | * Redacting a payment method does not delete it. Its transaction history is maintained as your permanent record. However, 314 | * all sensitive information (e.g. PAN, CVV) is removed immediately and permanently. A redacted payment method can no longer 315 | * be used for transactions since the account information will have been disposed of. Spreedly does not charge storage fees 316 | * on redacted payment methods. 317 | *

318 | * Most of the time, simply redacting a payment method will suffice because payment methods are for the most part only stored in 319 | * Spreedly. There are times though when a payment method is stored on the gateway and you'd like to notify the gateway that it 320 | * can no longer be used. In a case like this, if you just did a redact, then it's true that you'd no longer be able to use that 321 | * payment method with Spreedly, but it wouldn't stop you from using it directly through your gateway interface. 322 | *

323 | */ 324 | public SpreedlyTransactionResponse redact(final String paymentMethodToken, final String gatewayAccountToken) { 325 | SpreedlyPaymentMethodUpdate request = null; 326 | if (gatewayAccountToken != null) { 327 | request = new SpreedlyPaymentMethodUpdate(); 328 | request.gatewayAccountToken = gatewayAccountToken; 329 | } 330 | return util.put("https://core.spreedly.com/v1/payment_methods/" + paymentMethodToken + "/redact.xml", request, SpreedlyTransactionResponse.class); 331 | } 332 | 333 | /** 334 | * Redacting a payment method does not delete it. Its transaction history is maintained as your permanent record. However, 335 | * all sensitive information (e.g. PAN, CVV) is removed immediately and permanently. A redacted payment method can no longer 336 | * be used for transactions since the account information will have been disposed of. Spreedly does not charge storage fees 337 | * on redacted payment methods. 338 | */ 339 | public SpreedlyTransactionResponse redact(final String paymentMethodToken) { 340 | return redact(paymentMethodToken, null); 341 | } 342 | 343 | /** 344 | *

345 | * Unless specifically instructed to do otherwise, Core purges all of the sensitive data of payment methods it has seen every 346 | * few minutes. To keep the sensitive information of a payment method around for later, simply instruct Core to retain it. 347 | *

348 | * Passing the retain_on_success parameter to the purchase, verify, or authorize call can save you from having to make another 349 | * API call to do the retain. If the purchase, verify, or authorize succeeds, then the payment method is retained for you. 350 | *

351 | */ 352 | public SpreedlyTransactionResponse retain(final String paymentMethodToken) { 353 | return util.put("https://core.spreedly.com/v1/payment_methods/" + paymentMethodToken + "/retain.xml", null, SpreedlyTransactionResponse.class); 354 | } 355 | 356 | /** 357 | * Retrieve a single payment method by supplying the payment method key. 358 | */ 359 | public SpreedlyPaymentMethod getPaymentMethod(final String paymentMethodToken) { 360 | return util.get("https://core.spreedly.com/v1/payment_methods/" + paymentMethodToken, SpreedlyPaymentMethod.class); 361 | } 362 | 363 | /** 364 | * Retrieves a paginated list of all transactions for a gateway. 365 | * @param sinceToken the last token received in the previous list 366 | * @param desc if true, reverse the order to retrieve the most recent first 367 | */ 368 | public List listPaymentMethodTransactions(final String paymentMethodToken, final String sinceToken, final boolean desc) { 369 | String url = "https://core.spreedly.com/v1/payment_methods/" + paymentMethodToken + "/transactions.xml?order=" + 370 | (desc ? "desc" : "asc") + 371 | (sinceToken == null ? "" : "&since_token = " + sinceToken.trim()); 372 | SpreedlyTransactionListResponse r = util.get(url, SpreedlyTransactionListResponse.class); 373 | return r.transactions; 374 | } 375 | 376 | /** 377 | *

378 | * There are two ways to update a payment method. If you'd like to change the sensitive information like the credit card number 379 | * or the verification value, you'll want to just create and retain a new payment method using the usual transparent redirect approach, 380 | * redact the old payment method, and hold onto the token for the new payment method. This is the primary mechanism to use when you want 381 | * to give your customer the ability to update their card information. This process is described in detail as part of the Quickstart. 382 | *

383 | * There may be times, though, when you'd like to update a payment method without customer interaction. In this case, we provide an API 384 | * call to do so. It's important to note that updating the card number and verification_value is prohibited using this API call. 385 | *

386 | */ 387 | public SpreedlyPaymentMethod update(final SpreedlyPaymentMethod paymentMethod) { 388 | return util.put("https://core.spreedly.com/v1/payment_methods/" + paymentMethod.token + ".xml", paymentMethod, SpreedlyPaymentMethod.class); 389 | } 390 | 391 | } 392 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/SpreedlyException.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly; 2 | 3 | import cc.protea.util.http.Response; 4 | 5 | public class SpreedlyException extends RuntimeException { 6 | 7 | private static final long serialVersionUID = 1L; 8 | public Response response = null; 9 | public String errorMessage; 10 | public String errorCode; 11 | 12 | public SpreedlyException(final Exception e) { 13 | super(e); 14 | } 15 | 16 | public SpreedlyException(final Exception e, final Response response) { 17 | super(e); 18 | this.response = response; 19 | } 20 | 21 | public SpreedlyException(final Exception e, final String errorCode, final String errorMessage) { 22 | super(e); 23 | this.errorCode = errorCode; 24 | this.errorMessage = errorMessage; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/SpreedlyUtil.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.IOException; 5 | import java.io.StringWriter; 6 | 7 | import javax.xml.bind.DatatypeConverter; 8 | import javax.xml.bind.JAXBContext; 9 | import javax.xml.bind.JAXBException; 10 | import javax.xml.bind.Marshaller; 11 | import javax.xml.bind.Unmarshaller; 12 | 13 | import cc.protea.spreedly.model.internal.SpreedlyErrorHash; 14 | import cc.protea.spreedly.model.internal.SpreedlyErrorSetting; 15 | import cc.protea.spreedly.model.internal.SpreedlyErrors; 16 | import cc.protea.util.http.Request; 17 | import cc.protea.util.http.Response; 18 | 19 | class SpreedlyUtil { 20 | 21 | private final String environmentKey; 22 | private final String apiSecret; 23 | 24 | public SpreedlyUtil(final String environmentKey, final String apiSecret) { 25 | this.environmentKey = environmentKey; 26 | this.apiSecret = apiSecret; 27 | } 28 | 29 | T options(final String url, final Class type) { 30 | Response response = null; 31 | try { 32 | response = getService(url).optionsResource(); 33 | return convert(response.getBody(), type); 34 | } catch (SpreedlyException e) { 35 | return addError(type, e); 36 | } catch (IOException e) { 37 | throw new SpreedlyException(e, response); 38 | } 39 | } 40 | 41 | T get(final String url, final Class type) { 42 | Response response = null; 43 | try { 44 | response = getService(url).getResource(); 45 | return convert(response.getBody(), type); 46 | } catch (SpreedlyException e) { 47 | return addError(type, e); 48 | } catch (IOException e) { 49 | throw new SpreedlyException(e, response); 50 | } 51 | } 52 | 53 | T delete(final String url, final Object bodyObject, final Class type) { 54 | Response response = null; 55 | try { 56 | String body = convert(bodyObject); 57 | response = getService(url).setBody(body).deleteResource(); 58 | return convert(response.getBody(), type); 59 | } catch (SpreedlyException e) { 60 | return addError(type, e); 61 | } catch (IOException e) { 62 | throw new SpreedlyException(e, response); 63 | } 64 | } 65 | 66 | void delete(final String url, final Object bodyObject) { 67 | Response response = null; 68 | try { 69 | String body = convert(bodyObject); 70 | response = getService(url).setBody(body).deleteResource(); 71 | } catch (IOException e) { 72 | throw new SpreedlyException(e, response); 73 | } 74 | } 75 | 76 | T put(final String url, final Object bodyObject, final Class type) { 77 | Response response = null; 78 | try { 79 | String body = convert(bodyObject); 80 | response = getService(url).setBody(body).putResource(); 81 | return convert(response.getBody(), type); 82 | } catch (SpreedlyException e) { 83 | return addError(type, e); 84 | } catch (IOException e) { 85 | throw new SpreedlyException(e, response); 86 | } 87 | } 88 | 89 | T post(final String url, final Object bodyObject, final Class type) { 90 | Response response = null; 91 | try { 92 | String body = convert(bodyObject); 93 | response = getService(url).setBody(body).postResource(); 94 | return convert(response.getBody(), type); 95 | } catch (SpreedlyException e) { 96 | return addError(type, e); 97 | } catch (IOException e) { 98 | throw new SpreedlyException(e, response); 99 | } 100 | } 101 | 102 | private String getAuthorizationHeader() { 103 | final String pair = this.environmentKey + ":" + this.apiSecret; 104 | final String base64 = DatatypeConverter.printBase64Binary(pair.getBytes()); 105 | return "Basic " + base64; 106 | } 107 | 108 | private Request getService(final String url) { 109 | return new Request(url) 110 | .addHeader("Authorization", getAuthorizationHeader()) 111 | .addHeader("Accept", "application/xml") 112 | .addHeader("Content-Type", "application/xml"); 113 | } 114 | 115 | T convert(final String xml, final Class type) { 116 | return convert(xml, type, true); 117 | } 118 | 119 | @SuppressWarnings("unchecked") 120 | T convert(final String xml, final Class type, final boolean handleErrors) { 121 | if (xml == null) { 122 | return null; 123 | } 124 | if (String.class.equals(type)) { 125 | return (T) xml; 126 | } 127 | try { 128 | JAXBContext context = JAXBContext.newInstance(type); 129 | Unmarshaller un = context.createUnmarshaller(); 130 | ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes()); 131 | return (T) un.unmarshal(is); 132 | } catch (JAXBException e) { 133 | if (! handleErrors) { 134 | throw new SpreedlyException(e); 135 | } 136 | if (xml.contains("")) { 137 | SpreedlyErrors errors = convert(xml, SpreedlyErrors.class, false); 138 | throw new SpreedlyException(e, errors.errors.get(0).key, errors.errors.get(0).error); 139 | } 140 | if (xml.contains("")) { 141 | SpreedlyErrorHash hash = convert(xml, SpreedlyErrorHash.class, false); 142 | throw new SpreedlyException(e, hash.status, hash.error); 143 | } 144 | throw new SpreedlyException(e); 145 | } 146 | } 147 | 148 | T addError(final Class type, final SpreedlyException in) { 149 | try { 150 | return addError(type.newInstance(), in); 151 | } catch (SpreedlyException se) { 152 | throw se; 153 | } catch (Exception e) { 154 | throw new SpreedlyException(e); 155 | } 156 | } 157 | 158 | private T addError(final T in, final SpreedlyException e) { 159 | if (in instanceof SpreedlyErrorSetting) { 160 | SpreedlyErrorSetting ses = (SpreedlyErrorSetting) in; 161 | ses.setError(e.errorCode, e.errorMessage); 162 | return in; 163 | } else { 164 | // update exception message to reflect gateway error 165 | RuntimeException informativeException = new RuntimeException(e.errorCode + " : " + e.errorMessage, e); 166 | throw new SpreedlyException(informativeException, e.errorCode, e.errorMessage); 167 | } 168 | } 169 | 170 | private String convert(final Object object) { 171 | try { 172 | if (object == null) { 173 | return ""; 174 | } 175 | JAXBContext context = JAXBContext.newInstance(object.getClass()); 176 | Marshaller marshaller = context.createMarshaller(); 177 | StringWriter writer = new StringWriter(); 178 | marshaller.marshal(object, writer); 179 | return writer.toString(); 180 | } catch (JAXBException e) { 181 | throw new SpreedlyException(e); 182 | } 183 | } 184 | 185 | } 186 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/SpreedlyApiURLs.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model; 2 | 3 | import javax.xml.bind.annotation.XmlAccessType; 4 | import javax.xml.bind.annotation.XmlAccessorType; 5 | import javax.xml.bind.annotation.XmlElement; 6 | 7 | @XmlAccessorType(XmlAccessType.FIELD) 8 | public class SpreedlyApiURLs { 9 | 10 | @XmlElement(name = "callback_conversations") public String callbackConversations; 11 | 12 | public String getCallbackConversations() { 13 | return callbackConversations; 14 | } 15 | 16 | public SpreedlyApiURLs setCallbackConversations(final String callbackConversations) { 17 | this.callbackConversations = callbackConversations; 18 | return this; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/SpreedlyAvsResponse.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model; 2 | 3 | import javax.xml.bind.annotation.XmlEnum; 4 | import javax.xml.bind.annotation.XmlEnumValue; 5 | import javax.xml.bind.annotation.XmlType; 6 | 7 | @XmlType 8 | @XmlEnum(String.class) 9 | public enum SpreedlyAvsResponse { 10 | 11 | @XmlEnumValue("A") POSTAL_CODE_MISMATCH, 12 | @XmlEnumValue("B") POSTAL_CODE_NOT_VERIFIED, 13 | @XmlEnumValue("C") ADDRESS_AND_POSTAL_CODE_MISMATCH_C, 14 | @XmlEnumValue("D") ADDRESS_AND_POSTAL_CODE_MATCH_D, 15 | @XmlEnumValue("E") AVS_DATA_INVALID, 16 | @XmlEnumValue("F") NAME_MISMATCH_POSTAL_CODE_MATCH, 17 | @XmlEnumValue("G") INTERNATIONAL_BANK_AVS_UNSUPPORTED, 18 | @XmlEnumValue("H") NAME_MISMATCH_ADDRESS_AND_POSTAL_CODE_MATCH, 19 | @XmlEnumValue("I") ADDRESS_NOT_VERIFIED, 20 | @XmlEnumValue("J") NAME_ADDRESS_AND_POSTAL_CODE_MATCH_J, 21 | @XmlEnumValue("K") NAME_MATCH_ADDRESS_AND_POSTAL_CODE_MISMATCH, 22 | @XmlEnumValue("L") NAME_AND_POSTAL_CODE_MATCH_ADDRESS_MISMATCH, 23 | @XmlEnumValue("M") ADDRESS_AND_POSTAL_CODE_MATCH_M, 24 | @XmlEnumValue("N") ADDRESS_AND_POSTAL_CODE_MISMATCH_N, 25 | @XmlEnumValue("O") NAME_AND_ADDRESS_MATCH_POSTAL_CODE_MISMATCH, 26 | @XmlEnumValue("P") POSTAL_CODE_MATCH_ADDRESS_NOT_VERIFIED, 27 | @XmlEnumValue("Q") NAME_ADDRESS_AND_POSTAL_CODE_MATCH_Q, 28 | @XmlEnumValue("R") SYSTEM_UNAVAILABLE, 29 | @XmlEnumValue("S") BANK_AVS_UNSUPPORTED, 30 | @XmlEnumValue("T") NAME_MISMATCH_ADDRESS_MATCH, 31 | @XmlEnumValue("U") ADDRESS_INFORMATION_UNAVAILABLE, 32 | @XmlEnumValue("V") NAME_ADDRESS_AND_POSTAL_CODE_MATCH_V, 33 | @XmlEnumValue("W") ADDRESS_MISMATCH_POSTAL_CODE_MATCH_W, 34 | @XmlEnumValue("X") ADDRESS_AND_POSTAL_CODE_MATCH_X, 35 | @XmlEnumValue("Y") ADDRESS_AND_POSTAL_CODE_MATCH_Y, 36 | @XmlEnumValue("Z") ADDRESS_MISMATCH_POSTAL_CODE_MATCH_Z 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/SpreedlyCardType.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model; 2 | 3 | import javax.xml.bind.annotation.XmlEnum; 4 | import javax.xml.bind.annotation.XmlEnumValue; 5 | import javax.xml.bind.annotation.XmlType; 6 | 7 | @XmlType 8 | @XmlEnum(String.class) 9 | public enum SpreedlyCardType { 10 | 11 | @XmlEnumValue("visa") VISA, 12 | @XmlEnumValue("master") MASTERCARD, 13 | @XmlEnumValue("american_express") AMEX, 14 | @XmlEnumValue("discover") DISCOVER, 15 | @XmlEnumValue("dankort") DANKORT, 16 | @XmlEnumValue("jcb") JCB, 17 | @XmlEnumValue("diners_club") DINERS_CLUB 18 | 19 | } -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/SpreedlyCreditCard.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model; 2 | 3 | import javax.xml.bind.annotation.XmlAccessType; 4 | import javax.xml.bind.annotation.XmlAccessorType; 5 | import javax.xml.bind.annotation.XmlElement; 6 | import javax.xml.bind.annotation.XmlRootElement; 7 | 8 | @XmlRootElement(name = "credit_card") 9 | @XmlAccessorType(XmlAccessType.FIELD) 10 | public class SpreedlyCreditCard { 11 | 12 | @XmlElement(name = "first_name") public String firstName; 13 | @XmlElement(name = "last_name") public String lastName; 14 | @XmlElement(name = "full_name") public String fullName; 15 | public String number; 16 | @XmlElement(name = "track_data") public String trackData; 17 | public Integer month; 18 | public Integer year; 19 | @XmlElement(name = "verification_value") public String verificationValue; 20 | @XmlElement(name = "card_type") public SpreedlyCardType cardType; 21 | public String address1; 22 | public String address2; 23 | public String city; 24 | public String state; 25 | public String zip; 26 | public String country; 27 | @XmlElement(name = "phone_number") public String phoneNumber; 28 | @XmlElement(name = "shipping_address1") public String shippingAddress1; 29 | @XmlElement(name = "shipping_address2") public String shippingAddress2; 30 | @XmlElement(name = "shipping_city") public String shippingCity; 31 | @XmlElement(name = "shipping_state") public String shippingState; 32 | @XmlElement(name = "shipping_zip") public String shippingZip; 33 | @XmlElement(name = "shipping_country") public String shippingCountry; 34 | @XmlElement(name = "shipping_phone_number") public String shippingPhoneNumber; 35 | public String email; 36 | public Object data; 37 | public String getFirstName() { 38 | return firstName; 39 | } 40 | public void setFirstName(final String firstName) { 41 | this.firstName = firstName; 42 | } 43 | public String getLastName() { 44 | return lastName; 45 | } 46 | public void setLastName(final String lastName) { 47 | this.lastName = lastName; 48 | } 49 | public String getFullName() { 50 | return fullName; 51 | } 52 | public void setFullName(final String fullName) { 53 | this.fullName = fullName; 54 | } 55 | public String getNumber() { 56 | return number; 57 | } 58 | public void setNumber(final String number) { 59 | this.number = number; 60 | } 61 | public String getTrackData() { 62 | return trackData; 63 | } 64 | public void setTrackData(final String trackData) { 65 | this.trackData = trackData; 66 | } 67 | public Integer getMonth() { 68 | return month; 69 | } 70 | public void setMonth(final Integer month) { 71 | this.month = month; 72 | } 73 | public Integer getYear() { 74 | return year; 75 | } 76 | public void setYear(final Integer year) { 77 | this.year = year; 78 | } 79 | public String getVerificationValue() { 80 | return verificationValue; 81 | } 82 | public void setVerificationValue(final String verificationValue) { 83 | this.verificationValue = verificationValue; 84 | } 85 | public SpreedlyCardType getCardType() { 86 | return cardType; 87 | } 88 | public void setCardType(final SpreedlyCardType cardType) { 89 | this.cardType = cardType; 90 | } 91 | public String getAddress1() { 92 | return address1; 93 | } 94 | public void setAddress1(final String address1) { 95 | this.address1 = address1; 96 | } 97 | public String getAddress2() { 98 | return address2; 99 | } 100 | public void setAddress2(final String address2) { 101 | this.address2 = address2; 102 | } 103 | public String getCity() { 104 | return city; 105 | } 106 | public void setCity(final String city) { 107 | this.city = city; 108 | } 109 | public String getState() { 110 | return state; 111 | } 112 | public void setState(final String state) { 113 | this.state = state; 114 | } 115 | public String getZip() { 116 | return zip; 117 | } 118 | public void setZip(final String zip) { 119 | this.zip = zip; 120 | } 121 | public String getCountry() { 122 | return country; 123 | } 124 | public void setCountry(final String country) { 125 | this.country = country; 126 | } 127 | public String getPhoneNumber() { 128 | return phoneNumber; 129 | } 130 | public void setPhoneNumber(final String phoneNumber) { 131 | this.phoneNumber = phoneNumber; 132 | } 133 | public String getShippingAddress1() { 134 | return shippingAddress1; 135 | } 136 | public void setShippingAddress1(final String shippingAddress1) { 137 | this.shippingAddress1 = shippingAddress1; 138 | } 139 | public String getShippingAddress2() { 140 | return shippingAddress2; 141 | } 142 | public void setShippingAddress2(final String shippingAddress2) { 143 | this.shippingAddress2 = shippingAddress2; 144 | } 145 | public String getShippingCity() { 146 | return shippingCity; 147 | } 148 | public void setShippingCity(final String shippingCity) { 149 | this.shippingCity = shippingCity; 150 | } 151 | public String getShippingState() { 152 | return shippingState; 153 | } 154 | public void setShippingState(final String shippingState) { 155 | this.shippingState = shippingState; 156 | } 157 | public String getShippingZip() { 158 | return shippingZip; 159 | } 160 | public void setShippingZip(final String shippingZip) { 161 | this.shippingZip = shippingZip; 162 | } 163 | public String getShippingCountry() { 164 | return shippingCountry; 165 | } 166 | public void setShippingCountry(final String shippingCountry) { 167 | this.shippingCountry = shippingCountry; 168 | } 169 | public String getShippingPhoneNumber() { 170 | return shippingPhoneNumber; 171 | } 172 | public void setShippingPhoneNumber(final String shippingPhoneNumber) { 173 | this.shippingPhoneNumber = shippingPhoneNumber; 174 | } 175 | public String getEmail() { 176 | return email; 177 | } 178 | public void setEmail(final String email) { 179 | this.email = email; 180 | } 181 | public Object getData() { 182 | return data; 183 | } 184 | public void setData(final Object data) { 185 | this.data = data; 186 | } 187 | 188 | 189 | } 190 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/SpreedlyCvvResponse.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model; 2 | 3 | import javax.xml.bind.annotation.XmlEnum; 4 | import javax.xml.bind.annotation.XmlEnumValue; 5 | import javax.xml.bind.annotation.XmlType; 6 | 7 | @XmlType 8 | @XmlEnum(String.class) 9 | public enum SpreedlyCvvResponse { 10 | 11 | @XmlEnumValue("D") SUSPICIOUS_TRANSACTION, 12 | @XmlEnumValue("I") FAILED_DATA_VALIDATION_CHECK, 13 | @XmlEnumValue("M") MATCH, 14 | @XmlEnumValue("N") NO_MATCH, 15 | @XmlEnumValue("P") NOT_PROCESSED, 16 | @XmlEnumValue("S") SHOULD_HAVE_BEEN_PRESENT, 17 | @XmlEnumValue("U") ISSUER_UNABLE_TO_PROCESS_REQUEST, 18 | @XmlEnumValue("X") CARD_DOES_NOT_SUPPORT_VERIFICATION 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/SpreedlyGatewayAccount.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Date; 5 | import java.util.List; 6 | 7 | import javax.xml.bind.annotation.XmlAccessType; 8 | import javax.xml.bind.annotation.XmlAccessorType; 9 | import javax.xml.bind.annotation.XmlElement; 10 | import javax.xml.bind.annotation.XmlElementWrapper; 11 | import javax.xml.bind.annotation.XmlRootElement; 12 | 13 | @XmlRootElement(name = "gateway") 14 | @XmlAccessorType(XmlAccessType.FIELD) 15 | public class SpreedlyGatewayAccount { 16 | 17 | public String token; 18 | @XmlElement(name = "gateway_type") public String gatewayType; 19 | public String name; 20 | public SpreedlyGatewayCharacteristics characteristics = new SpreedlyGatewayCharacteristics(); 21 | @XmlElementWrapper(name = "credentials") 22 | @XmlElement(name = "credential") 23 | public List credentials = new ArrayList(); 24 | @XmlElementWrapper(name = "gateway_specific_fields") 25 | @XmlElement(name = "gateway_specific_field") 26 | public List gatewaySpecificFields = new ArrayList(); 27 | @XmlElementWrapper(name = "payment_methods") 28 | @XmlElement(name = "payment_method") 29 | public List paymentMethods = new ArrayList(); 30 | public SpreedlyGatewayAccountState state; 31 | public boolean redacted; 32 | @XmlElement(name = "created_at") public Date createdOn; 33 | @XmlElement(name = "updated_at") public Date updatedOn; 34 | @XmlElement(name = "description") public String description; 35 | public String getToken() { 36 | return token; 37 | } 38 | public void setToken(final String token) { 39 | this.token = token; 40 | } 41 | public String getGatewayType() { 42 | return gatewayType; 43 | } 44 | public void setGatewayType(final String gatewayType) { 45 | this.gatewayType = gatewayType; 46 | } 47 | public String getName() { 48 | return name; 49 | } 50 | public void setName(final String name) { 51 | this.name = name; 52 | } 53 | public SpreedlyGatewayCharacteristics getCharacteristics() { 54 | return characteristics; 55 | } 56 | public void setCharacteristics(final SpreedlyGatewayCharacteristics characteristics) { 57 | this.characteristics = characteristics; 58 | } 59 | public List getCredentials() { 60 | return credentials; 61 | } 62 | public void setCredentials(final List credentials) { 63 | this.credentials = credentials; 64 | } 65 | public List getGatewaySpecificFields() { 66 | return gatewaySpecificFields; 67 | } 68 | public void setGatewaySpecificFields(final List gatewaySpecificFields) { 69 | this.gatewaySpecificFields = gatewaySpecificFields; 70 | } 71 | public List getPaymentMethods() { 72 | return paymentMethods; 73 | } 74 | public void setPaymentMethods(final List paymentMethods) { 75 | this.paymentMethods = paymentMethods; 76 | } 77 | public SpreedlyGatewayAccountState getState() { 78 | return state; 79 | } 80 | public void setState(final SpreedlyGatewayAccountState state) { 81 | this.state = state; 82 | } 83 | public boolean isRedacted() { 84 | return redacted; 85 | } 86 | public void setRedacted(final boolean redacted) { 87 | this.redacted = redacted; 88 | } 89 | public Date getCreatedOn() { 90 | return createdOn; 91 | } 92 | public void setCreatedOn(final Date createdOn) { 93 | this.createdOn = createdOn; 94 | } 95 | public Date getUpdatedOn() { 96 | return updatedOn; 97 | } 98 | public void setUpdatedOn(final Date updatedOn) { 99 | this.updatedOn = updatedOn; 100 | } 101 | public String getDescription() { 102 | return description; 103 | } 104 | public void setDescription(final String description) { 105 | this.description = description; 106 | } 107 | 108 | } -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/SpreedlyGatewayAccountState.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model; 2 | 3 | import javax.xml.bind.annotation.XmlEnum; 4 | import javax.xml.bind.annotation.XmlEnumValue; 5 | import javax.xml.bind.annotation.XmlType; 6 | 7 | @XmlType 8 | @XmlEnum(String.class) 9 | public enum SpreedlyGatewayAccountState { 10 | 11 | @XmlEnumValue("retained") RETAINED, 12 | @XmlEnumValue("redacted") REDACTED 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/SpreedlyGatewayAuthMode.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import javax.xml.bind.annotation.XmlAccessType; 7 | import javax.xml.bind.annotation.XmlAccessorType; 8 | import javax.xml.bind.annotation.XmlElement; 9 | import javax.xml.bind.annotation.XmlElementWrapper; 10 | 11 | /** 12 | * Describes fields that are required to authenticate with a gateways. There may be multiple modes. 13 | * @author rjstanford 14 | * 15 | */ 16 | @XmlAccessorType(XmlAccessType.FIELD) 17 | public class SpreedlyGatewayAuthMode { 18 | 19 | /** 20 | * Spreedly assigned word identifying the collection of credentials. 21 | */ 22 | @XmlElement(name = "auth_mode_type") public String type; 23 | 24 | /** 25 | * Spreedly assigned phrase identifying the collection of credentials. 26 | */ 27 | public String name; 28 | 29 | /** 30 | * These credentials are stored to be able to authenticate when performing gateway transactions. 31 | */ 32 | @XmlElementWrapper(name = "credentials") 33 | @XmlElement(name = "credential") public List credentials = new ArrayList(); 34 | 35 | /** 36 | * @return Spreedly assigned word identifying the collection of credentials. 37 | */ 38 | public String getType() { 39 | return type; 40 | } 41 | /** 42 | * @param type Spreedly assigned word identifying the collection of credentials. 43 | */ 44 | public void setType(final String type) { 45 | this.type = type; 46 | } 47 | 48 | /** 49 | * @return Spreedly assigned phrase identifying the collection of credentials. 50 | */ 51 | public String getName() { 52 | return name; 53 | } 54 | /** 55 | * @param name Spreedly assigned phrase identifying the collection of credentials. 56 | */ 57 | public void setName(final String name) { 58 | this.name = name; 59 | } 60 | 61 | /** 62 | * @return These credentials are stored to be able to authenticate when performing gateway transactions. 63 | */ 64 | public List getCredentials() { 65 | return credentials; 66 | } 67 | /** 68 | * @param credentials These credentials are stored to be able to authenticate when performing gateway transactions. 69 | */ 70 | public void setCredentials(final List credentials) { 71 | this.credentials = credentials; 72 | } 73 | 74 | 75 | } -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/SpreedlyGatewayCharacteristics.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model; 2 | 3 | import javax.xml.bind.annotation.XmlAccessType; 4 | import javax.xml.bind.annotation.XmlAccessorType; 5 | import javax.xml.bind.annotation.XmlElement; 6 | 7 | @XmlAccessorType(XmlAccessType.FIELD) 8 | public class SpreedlyGatewayCharacteristics { 9 | 10 | @XmlElement(name = "supports_purchase") public boolean supportsPurchase; 11 | @XmlElement(name = "supports_authorize") public boolean supportsAuthorize; 12 | @XmlElement(name = "supports_capture") public boolean supportsCapture; 13 | @XmlElement(name = "supports_credit") public boolean supportsCredit; 14 | @XmlElement(name = "supports_general_credit") public boolean supportsGeneralCredit; 15 | @XmlElement(name = "supports_void") public boolean supportsVoid; 16 | @XmlElement(name = "supports_verify") public boolean supportsVerify; 17 | @XmlElement(name = "supports_reference_purchase") public boolean supportsReferencePurchase; 18 | @XmlElement(name = "supports_purchase_via_preauthorization") public boolean supportsPurchaseViaPreauthorization; 19 | @XmlElement(name = "supports_offsite_purchase") public boolean supportsOffsitePurchase; 20 | @XmlElement(name = "supports_offsite_authorize") public boolean supportsOffsiteAuthorize; 21 | @XmlElement(name = "supports_3dsecure_purchase") public boolean supports3DSecurePurchase; 22 | @XmlElement(name = "supports_3dsecure_authorize") public boolean supports3DSecureAuthorize; 23 | @XmlElement(name = "supports_store") public boolean supportsStore; 24 | @XmlElement(name = "supports_remove") public boolean supportsRemove; 25 | @XmlElement(name = "supports_disburse") public boolean supportsDisburse; 26 | @XmlElement(name = "supports_fraud_review") public boolean supportsFraudReview; 27 | 28 | public boolean isSupportsPurchase() { 29 | return supportsPurchase; 30 | } 31 | public void setSupportsPurchase(final boolean supportsPurchase) { 32 | this.supportsPurchase = supportsPurchase; 33 | } 34 | public boolean isSupportsAuthorize() { 35 | return supportsAuthorize; 36 | } 37 | public void setSupportsAuthorize(final boolean supportsAuthorize) { 38 | this.supportsAuthorize = supportsAuthorize; 39 | } 40 | public boolean isSupportsCapture() { 41 | return supportsCapture; 42 | } 43 | public void setSupportsCapture(final boolean supportsCapture) { 44 | this.supportsCapture = supportsCapture; 45 | } 46 | public boolean isSupportsCredit() { 47 | return supportsCredit; 48 | } 49 | public void setSupportsCredit(final boolean supportsCredit) { 50 | this.supportsCredit = supportsCredit; 51 | } 52 | public boolean isSupportsGeneralCredit() { 53 | return supportsGeneralCredit; 54 | } 55 | public void setSupportsGeneralCredit(final boolean supportsGeneralCredit) { 56 | this.supportsGeneralCredit = supportsGeneralCredit; 57 | } 58 | public boolean isSupportsVoid() { 59 | return supportsVoid; 60 | } 61 | public void setSupportsVoid(final boolean supportsVoid) { 62 | this.supportsVoid = supportsVoid; 63 | } 64 | public boolean isSupportsVerify() { 65 | return supportsVerify; 66 | } 67 | public void setSupportsVerify(final boolean supportsVerify) { 68 | this.supportsVerify = supportsVerify; 69 | } 70 | public boolean isSupportsReferencePurchase() { 71 | return supportsReferencePurchase; 72 | } 73 | public void setSupportsReferencePurchase(final boolean supportsReferencePurchase) { 74 | this.supportsReferencePurchase = supportsReferencePurchase; 75 | } 76 | public boolean isSupportsPurchaseViaPreauthorization() { 77 | return supportsPurchaseViaPreauthorization; 78 | } 79 | public void setSupportsPurchaseViaPreauthorization(final boolean supportsPurchaseViaPreauthorization) { 80 | this.supportsPurchaseViaPreauthorization = supportsPurchaseViaPreauthorization; 81 | } 82 | public boolean isSupportsOffsitePurchase() { 83 | return supportsOffsitePurchase; 84 | } 85 | public void setSupportsOffsitePurchase(final boolean supportsOffsitePurchase) { 86 | this.supportsOffsitePurchase = supportsOffsitePurchase; 87 | } 88 | public boolean isSupportsOffsiteAuthorize() { 89 | return supportsOffsiteAuthorize; 90 | } 91 | public void setSupportsOffsiteAuthorize(final boolean supportsOffsiteAuthorize) { 92 | this.supportsOffsiteAuthorize = supportsOffsiteAuthorize; 93 | } 94 | public boolean isSupports3DSecurePurchase() { 95 | return supports3DSecurePurchase; 96 | } 97 | public void setSupports3DSecurePurchase(final boolean supports3dSecurePurchase) { 98 | supports3DSecurePurchase = supports3dSecurePurchase; 99 | } 100 | public boolean isSupports3DSecureAuthorize() { 101 | return supports3DSecureAuthorize; 102 | } 103 | public void setSupports3DSecureAuthorize(final boolean supports3dSecureAuthorize) { 104 | supports3DSecureAuthorize = supports3dSecureAuthorize; 105 | } 106 | public boolean isSupportsStore() { 107 | return supportsStore; 108 | } 109 | public void setSupportsStore(final boolean supportsStore) { 110 | this.supportsStore = supportsStore; 111 | } 112 | public boolean isSupportsRemove() { 113 | return supportsRemove; 114 | } 115 | public void setSupportsRemove(final boolean supportsRemove) { 116 | this.supportsRemove = supportsRemove; 117 | } 118 | public boolean isSupportsDisburse() { 119 | return supportsDisburse; 120 | } 121 | public void setsSupportsDisburse(final boolean supportsDisburse) { 122 | this.supportsDisburse = supportsDisburse; 123 | } 124 | public boolean isSupportsFraudReview() { 125 | return supportsFraudReview; 126 | } 127 | public void setsSupportsFraudReview(final boolean supportsFraudReview) { 128 | this.supportsFraudReview = supportsFraudReview; 129 | } 130 | 131 | 132 | } 133 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/SpreedlyGatewayCredential.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model; 2 | 3 | import javax.xml.bind.annotation.XmlAccessType; 4 | import javax.xml.bind.annotation.XmlAccessorType; 5 | 6 | @XmlAccessorType(XmlAccessType.FIELD) 7 | public class SpreedlyGatewayCredential { 8 | 9 | /** 10 | * The Spreedly key for the credential. 11 | */ 12 | public String name; 13 | /** 14 | * A human name for the field. 15 | */ 16 | public String label; 17 | /** 18 | * The value associated with the named credential 19 | */ 20 | public String value; 21 | /** 22 | * Indicates that you can safely show the credentials to users (i.e. you can use a cleartext field rather than a password field). 23 | * Safe fields will also be returned when you pull the gateway, whereas non-safe fields will never be returned to you. 24 | */ 25 | public boolean safe; 26 | /** 27 | * Indicates a large credential that needs a large text field, such as a certificate that needs to be pasted in. 28 | */ 29 | public boolean large; 30 | 31 | /** 32 | * @return The Spreedly key for the credential. 33 | */ 34 | public String getName() { 35 | return name; 36 | } 37 | /** 38 | * @param name The Spreedly key for the credential. 39 | */ 40 | public void setName(final String name) { 41 | this.name = name; 42 | } 43 | 44 | /** 45 | * @return a human name for the field. 46 | */ 47 | public String getLabel() { 48 | return label; 49 | } 50 | /** 51 | * @param label a human name for the field. 52 | */ 53 | public void setLabel(final String label) { 54 | this.label = label; 55 | } 56 | 57 | /** 58 | * @return the value associated with the named credential 59 | */ 60 | public String getValue() { 61 | return value; 62 | } 63 | /** 64 | * @param value the value associated with the named credential 65 | */ 66 | public void setValue(final String value) { 67 | this.value = value; 68 | } 69 | 70 | /** 71 | * @return Indicates that you can safely show the credentials to users (i.e. you can use a cleartext field rather than a password field). 72 | * Safe fields will also be returned when you pull the gateway, whereas non-safe fields will never be returned to you. 73 | */ 74 | public boolean isSafe() { 75 | return safe; 76 | } 77 | /** 78 | * @param safe Indicates that you can safely show the credentials to users (i.e. you can use a cleartext field rather than a password field). 79 | * Safe fields will also be returned when you pull the gateway, whereas non-safe fields will never be returned to you. 80 | */ 81 | public void setSafe(final boolean safe) { 82 | this.safe = safe; 83 | } 84 | 85 | /** 86 | * @return indicates a large credential that needs a large text field, such as a certificate that needs to be pasted in. 87 | */ 88 | public boolean isLarge() { 89 | return large; 90 | } 91 | /** 92 | * @param large indicates a large credential that needs a large text field, such as a certificate that needs to be pasted in. 93 | */ 94 | public void setLarge(final boolean large) { 95 | this.large = large; 96 | } 97 | 98 | } -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/SpreedlyGatewayPaymentMethod.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model; 2 | 3 | import javax.xml.bind.annotation.XmlEnum; 4 | import javax.xml.bind.annotation.XmlEnumValue; 5 | import javax.xml.bind.annotation.XmlType; 6 | 7 | @XmlType 8 | @XmlEnum(String.class) 9 | public enum SpreedlyGatewayPaymentMethod { 10 | 11 | @XmlEnumValue("credit_card") CREDIT_CARD, 12 | @XmlEnumValue("bank_account") BANK_ACCOUNT, 13 | @XmlEnumValue("paypal") PAYPAL 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/SpreedlyGatewayProvider.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import javax.xml.bind.annotation.XmlAccessType; 7 | import javax.xml.bind.annotation.XmlAccessorType; 8 | import javax.xml.bind.annotation.XmlElement; 9 | import javax.xml.bind.annotation.XmlElementWrapper; 10 | import javax.xml.bind.annotation.XmlTransient; 11 | 12 | @XmlAccessorType(XmlAccessType.FIELD) 13 | public class SpreedlyGatewayProvider { 14 | 15 | /** 16 | * A unique identifier for a gateway provider. 17 | */ 18 | @XmlElement(name="gateway_type") public String gatewayType; 19 | /** 20 | * The full descriptive name of a gateway provider. 21 | */ 22 | public String name; 23 | /** 24 | * Fields that are required to authenticate with a gateways. There may be multiple modes. These credentials are stored to be able to authenticate when performing gateway transactions. 25 | */ 26 | @XmlElement(name="auth_mode") @XmlElementWrapper(name = "auth_modes") public List authModes; 27 | /** 28 | * A list of properties containing boolean values describing what properties the gateway supports. 29 | */ 30 | @XmlElement(name="characteristics") public SpreedlyGatewayCharacteristics characteristics; 31 | /** 32 | * List of payment method types that the gateway supports. 33 | */ 34 | @XmlElementWrapper(name = "payment_methods") 35 | @XmlElement(name = "payment_method") 36 | public List paymentMethods = new ArrayList(); 37 | /** 38 | * Fields that a gateway defines for a specific purpose but is not implemented by all gateways. 39 | */ 40 | @XmlElementWrapper(name = "gateway_specific_fields") 41 | @XmlElement(name = "gateway_specific_field") 42 | public List gatewaySpecificFields = new ArrayList(); 43 | /** 44 | * Abbreviated country names where the gateway can process payments. 45 | */ 46 | @XmlTransient 47 | public List supportedCountries = new ArrayList(); 48 | /** 49 | * Global regions where the gateway can process payments. 50 | */ 51 | @XmlTransient 52 | public List regions = new ArrayList(); 53 | /** 54 | * URL of the gateway's website. 55 | */ 56 | public String homepage; 57 | /** 58 | * Name of the company that operates the gateway provider. 59 | */ 60 | @XmlElement(name = "company_name") public String companyName; 61 | 62 | /** 63 | * @return A unique identifier for a gateway provider. 64 | */ 65 | public String getGatewayType() { 66 | return gatewayType; 67 | } 68 | /** 69 | * @param gatewayType A unique identifier for a gateway provider. 70 | */ 71 | public void setGatewayType(final String gatewayType) { 72 | this.gatewayType = gatewayType; 73 | } 74 | 75 | /** 76 | * @return The full descriptive name of a gateway provider. 77 | */ 78 | public String getName() { 79 | return name; 80 | } 81 | /** 82 | * @param name The full descriptive name of a gateway provider. 83 | */ 84 | public void setName(final String name) { 85 | this.name = name; 86 | } 87 | 88 | /** 89 | * @return Fields that are required to authenticate with a gateways. There may be multiple modes. These credentials are stored to be able to authenticate when performing gateway transactions. 90 | */ 91 | public List getAuthModes() { 92 | return authModes; 93 | } 94 | /** 95 | * @param authModes Fields that are required to authenticate with a gateways. There may be multiple modes. These credentials are stored to be able to authenticate when performing gateway transactions. 96 | */ 97 | public void setAuthModes(final List authModes) { 98 | this.authModes = authModes; 99 | } 100 | 101 | /** 102 | * @return A list of properties containing boolean values describing what properties the gateway supports. 103 | */ 104 | public SpreedlyGatewayCharacteristics getCharacteristics() { 105 | return characteristics; 106 | } 107 | /** 108 | * @param characteristics A list of properties containing boolean values describing what properties the gateway supports. 109 | */ 110 | public void setCharacteristics(final SpreedlyGatewayCharacteristics characteristics) { 111 | this.characteristics = characteristics; 112 | } 113 | 114 | /** 115 | * @return List of payment method types that the gateway supports. 116 | */ 117 | public List getPaymentMethods() { 118 | return paymentMethods; 119 | } 120 | /** 121 | * @param paymentMethods List of payment method types that the gateway supports. 122 | */ 123 | public void setPaymentMethods(final List paymentMethods) { 124 | this.paymentMethods = paymentMethods; 125 | } 126 | 127 | /** 128 | * @return Fields that a gateway defines for a specific purpose but is not implemented by all gateways. 129 | */ 130 | public List getGatewaySpecificFields() { 131 | return gatewaySpecificFields; 132 | } 133 | /** 134 | * @param gatewaySpecificFields Fields that a gateway defines for a specific purpose but is not implemented by all gateways. 135 | */ 136 | public void setGatewaySpecificFields(final List gatewaySpecificFields) { 137 | this.gatewaySpecificFields = gatewaySpecificFields; 138 | } 139 | 140 | /** 141 | * @return Abbreviated country names where the gateway can process payments. 142 | */ 143 | public List getSupportedCountries() { 144 | return supportedCountries; 145 | } 146 | /** 147 | * @param supportedCountries Abbreviated country names where the gateway can process payments. 148 | */ 149 | public void setSupportedCountries(final List supportedCountries) { 150 | this.supportedCountries = supportedCountries; 151 | } 152 | 153 | /** 154 | * @return Global regions where the gateway can process payments. 155 | */ 156 | public List getRegions() { 157 | return regions; 158 | } 159 | /** 160 | * @param regions Global regions where the gateway can process payments. 161 | */ 162 | public void setRegions(final List regions) { 163 | this.regions = regions; 164 | } 165 | 166 | /** 167 | * @return URL of the gateway's website. 168 | */ 169 | public String getHomepage() { 170 | return homepage; 171 | } 172 | /** 173 | * @param homepage URL of the gateway's website. 174 | */ 175 | public void setHomepage(final String homepage) { 176 | this.homepage = homepage; 177 | } 178 | 179 | /** 180 | * @return Name of the company that operates the gateway provider. 181 | */ 182 | public String getCompanyName() { 183 | return companyName; 184 | } 185 | /** 186 | * @param companyName Name of the company that operates the gateway provider. 187 | */ 188 | public void setCompanyName(final String companyName) { 189 | this.companyName = companyName; 190 | } 191 | 192 | 193 | // Private XML hassles below here 194 | 195 | @XmlElement(name = "regions") 196 | private void setRegionString(final String in) { 197 | split(in, regions); 198 | } 199 | 200 | @XmlElement(name = "supported_countries") 201 | private void setSupportedCountryString(final String in) { 202 | split(in, supportedCountries); 203 | } 204 | 205 | private void split(final String in, final List list) { 206 | if (in == null) { 207 | list.clear(); 208 | return; 209 | } 210 | for (String item : in.split(",")) { 211 | list.add(item.trim()); 212 | } 213 | } 214 | 215 | } -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/SpreedlyGatewayRedactResponse.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model; 2 | 3 | import javax.xml.bind.annotation.XmlAccessType; 4 | import javax.xml.bind.annotation.XmlAccessorType; 5 | import javax.xml.bind.annotation.XmlRootElement; 6 | 7 | /** 8 | * Created by jason on 5/3/17. 9 | */ 10 | 11 | @XmlRootElement(name = "transaction") 12 | @XmlAccessorType(XmlAccessType.FIELD) 13 | public class SpreedlyGatewayRedactResponse { 14 | 15 | /** 16 | * A unique string generated by Spreedly to identify a transaction. 17 | */ 18 | public String token; 19 | 20 | /** 21 | * true if transaction was successful. 22 | */ 23 | public boolean succeeded; 24 | 25 | /** 26 | * true if gateway was redacted. 27 | */ 28 | public boolean redacted; 29 | 30 | public SpreedlyMessage message; 31 | 32 | public SpreedlyGatewayAccount gateway; 33 | 34 | public SpreedlyGatewayAccountState state; 35 | 36 | /** 37 | * @return true if transaction was successful. 38 | */ 39 | public boolean isSucceeded() { 40 | return succeeded; 41 | } 42 | /** 43 | * @param succeeded true if transaction was successful. 44 | */ 45 | public SpreedlyGatewayRedactResponse setSucceeded(final boolean succeeded) { 46 | this.succeeded = succeeded; 47 | return this; 48 | } 49 | 50 | public String getToken() { 51 | return token; 52 | } 53 | 54 | public void setToken(String token) { 55 | this.token = token; 56 | } 57 | 58 | public SpreedlyMessage getMessage() { 59 | return message; 60 | } 61 | 62 | public void setMessage(SpreedlyMessage message) { 63 | this.message = message; 64 | } 65 | 66 | public boolean isRedacted() { 67 | return redacted; 68 | } 69 | 70 | public void setRedacted(boolean redacted) { 71 | this.redacted = redacted; 72 | } 73 | 74 | public SpreedlyGatewayAccount getGateway() { 75 | return gateway; 76 | } 77 | 78 | public void setGateway(SpreedlyGatewayAccount gateway) { 79 | this.gateway = gateway; 80 | } 81 | 82 | public SpreedlyGatewayAccountState getState() { 83 | return state; 84 | } 85 | 86 | public void setState(SpreedlyGatewayAccountState state) { 87 | this.state = state; 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/SpreedlyMessage.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model; 2 | 3 | import javax.xml.bind.annotation.XmlAccessType; 4 | import javax.xml.bind.annotation.XmlAccessorType; 5 | import javax.xml.bind.annotation.XmlAttribute; 6 | import javax.xml.bind.annotation.XmlValue; 7 | 8 | @XmlAccessorType(XmlAccessType.FIELD) 9 | public class SpreedlyMessage { 10 | 11 | /** 12 | * The constant Spreedly key representing the results, useful for translation. 13 | */ 14 | @XmlAttribute public String key; 15 | 16 | /** 17 | * A brief description of the results of the transaction. 18 | */ 19 | @XmlValue public String message; 20 | 21 | /** 22 | * @return A brief description of the results of the transaction. 23 | */ 24 | public String toString() { 25 | return message; 26 | } 27 | 28 | /** 29 | * @return The constant Spreedly key representing the results, useful for translation. 30 | */ 31 | public String getKey() { 32 | return key; 33 | } 34 | 35 | /** 36 | * @param key The constant Spreedly key representing the results, useful for translation. 37 | */ 38 | public void setKey(final String key) { 39 | this.key = key; 40 | } 41 | 42 | /** 43 | * @return A brief description of the results of the transaction. 44 | */ 45 | public String getMessage() { 46 | return message; 47 | } 48 | 49 | /** 50 | * @param message A brief description of the results of the transaction. 51 | */ 52 | public void setMessage(final String message) { 53 | this.message = message; 54 | } 55 | 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/SpreedlyPaymentMethod.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Date; 5 | import java.util.List; 6 | 7 | import javax.xml.bind.annotation.XmlAccessType; 8 | import javax.xml.bind.annotation.XmlAccessorType; 9 | import javax.xml.bind.annotation.XmlElement; 10 | import javax.xml.bind.annotation.XmlElementWrapper; 11 | import javax.xml.bind.annotation.XmlRootElement; 12 | 13 | @XmlRootElement(name = "payment_method") 14 | @XmlAccessorType(XmlAccessType.FIELD) 15 | public class SpreedlyPaymentMethod { 16 | 17 | public String token; 18 | @XmlElement(name = "created_at") public Date createdOn; 19 | @XmlElement(name = "updated_at") public Date updatedOn; 20 | public String email; 21 | public String data; 22 | @XmlElement(name = "storage_state") public SpreedlyStorageState storageState; 23 | @XmlElement(name = "third_party_token") public String thirdPartyToken; 24 | public boolean test; 25 | @XmlElement(name = "last_four_digits") public String lastFourDigits; 26 | @XmlElement(name = "first_six_digits") public String firstSixDigits; 27 | @XmlElement(name = "card_type") public SpreedlyCardType cardType; 28 | @XmlElement(name = "first_name") public String firstName; 29 | @XmlElement(name = "last_name") public String lastName; 30 | public Integer month; 31 | public Integer year; 32 | public String address1; 33 | public String address2; 34 | public String city; 35 | public String state; 36 | public String zip; 37 | public String country; 38 | @XmlElement(name = "phone_number") public String phoneNumber; 39 | @XmlElement(name = "shipping_address1") public String shippingAddress1; 40 | @XmlElement(name = "shipping_address2") public String shippingAddress2; 41 | @XmlElement(name = "shipping_city") public String shippingCity; 42 | @XmlElement(name = "shipping_state") public String shippingState; 43 | @XmlElement(name = "shipping_zip") public String shippingZip; 44 | @XmlElement(name = "shipping_country") public String shippingCountry; 45 | @XmlElement(name = "shipping_phone_number") public String shippingPhoneNumber; 46 | public String company; 47 | @XmlElement(name = "full_name") public String fullName; 48 | @XmlElement(name = "eligible_for_card_updater") public Boolean eligibleForCardUpdater; 49 | @XmlElement(name = "payment_method_type") public SpreedlyPaymentMethodType paymentMethodType; 50 | @XmlElement(name = "verification_value") public String verificationValue; 51 | @XmlElementWrapper(name = "errors") 52 | @XmlElement(name = "error") 53 | public List errors = new ArrayList(); 54 | @XmlElement(name = "api_urls") public SpreedlyApiURLs apiUrls; 55 | public String number; 56 | public String fingerprint; 57 | public String getToken() { 58 | return token; 59 | } 60 | public void setToken(final String token) { 61 | this.token = token; 62 | } 63 | public Date getCreatedOn() { 64 | return createdOn; 65 | } 66 | public void setCreatedOn(final Date createdOn) { 67 | this.createdOn = createdOn; 68 | } 69 | public Date getUpdatedOn() { 70 | return updatedOn; 71 | } 72 | public void setUpdatedOn(final Date updatedOn) { 73 | this.updatedOn = updatedOn; 74 | } 75 | public String getEmail() { 76 | return email; 77 | } 78 | public void setEmail(final String email) { 79 | this.email = email; 80 | } 81 | public String getData() { 82 | return data; 83 | } 84 | public void setData(final String data) { 85 | this.data = data; 86 | } 87 | public SpreedlyStorageState getStorageState() { 88 | return storageState; 89 | } 90 | public void setStorageState(final SpreedlyStorageState storageState) { 91 | this.storageState = storageState; 92 | } 93 | public String getThirdPartyToken() { 94 | return thirdPartyToken; 95 | } 96 | public void setThirdPartyToken(final String thirdPartyToken) { 97 | this.thirdPartyToken = thirdPartyToken; 98 | } 99 | public boolean isTest() { 100 | return test; 101 | } 102 | public void setTest(final boolean test) { 103 | this.test = test; 104 | } 105 | public String getLastFourDigits() { 106 | return lastFourDigits; 107 | } 108 | public void setLastFourDigits(final String lastFourDigits) { 109 | this.lastFourDigits = lastFourDigits; 110 | } 111 | public String getFirstSixDigits() { 112 | return firstSixDigits; 113 | } 114 | public void setFirstSixDigits(final String firstSixDigits) { 115 | this.firstSixDigits = firstSixDigits; 116 | } 117 | public SpreedlyCardType getCardType() { 118 | return cardType; 119 | } 120 | public void setCardType(final SpreedlyCardType cardType) { 121 | this.cardType = cardType; 122 | } 123 | public String getFirstName() { 124 | return firstName; 125 | } 126 | public void setFirstName(final String firstName) { 127 | this.firstName = firstName; 128 | } 129 | public String getLastName() { 130 | return lastName; 131 | } 132 | public void setLastName(final String lastName) { 133 | this.lastName = lastName; 134 | } 135 | public Integer getMonth() { 136 | return month; 137 | } 138 | public void setMonth(final Integer month) { 139 | this.month = month; 140 | } 141 | public Integer getYear() { 142 | return year; 143 | } 144 | public void setYear(final Integer year) { 145 | this.year = year; 146 | } 147 | public String getAddress1() { 148 | return address1; 149 | } 150 | public void setAddress1(final String address1) { 151 | this.address1 = address1; 152 | } 153 | public String getAddress2() { 154 | return address2; 155 | } 156 | public void setAddress2(final String address2) { 157 | this.address2 = address2; 158 | } 159 | public String getCity() { 160 | return city; 161 | } 162 | public void setCity(final String city) { 163 | this.city = city; 164 | } 165 | public String getState() { 166 | return state; 167 | } 168 | public void setState(final String state) { 169 | this.state = state; 170 | } 171 | public String getZip() { 172 | return zip; 173 | } 174 | public void setZip(final String zip) { 175 | this.zip = zip; 176 | } 177 | public String getCountry() { 178 | return country; 179 | } 180 | public void setCountry(final String country) { 181 | this.country = country; 182 | } 183 | public String getPhoneNumber() { 184 | return phoneNumber; 185 | } 186 | public void setPhoneNumber(final String phoneNumber) { 187 | this.phoneNumber = phoneNumber; 188 | } 189 | public String getShippingAddress1() { 190 | return shippingAddress1; 191 | } 192 | public void setShippingAddress1(final String shippingAddress1) { 193 | this.shippingAddress1 = shippingAddress1; 194 | } 195 | public String getShippingAddress2() { 196 | return shippingAddress2; 197 | } 198 | public void setShippingAddress2(final String shippingAddress2) { 199 | this.shippingAddress2 = shippingAddress2; 200 | } 201 | public String getShippingCity() { 202 | return shippingCity; 203 | } 204 | public void setShippingCity(final String shippingCity) { 205 | this.shippingCity = shippingCity; 206 | } 207 | public String getShippingState() { 208 | return shippingState; 209 | } 210 | public void setShippingState(final String shippingState) { 211 | this.shippingState = shippingState; 212 | } 213 | public String getShippingZip() { 214 | return shippingZip; 215 | } 216 | public void setShippingZip(final String shippingZip) { 217 | this.shippingZip = shippingZip; 218 | } 219 | public String getShippingCountry() { 220 | return shippingCountry; 221 | } 222 | public void setShippingCountry(final String shippingCountry) { 223 | this.shippingCountry = shippingCountry; 224 | } 225 | public String getShippingPhoneNumber() { 226 | return shippingPhoneNumber; 227 | } 228 | public void setShippingPhoneNumber(final String shippingPhoneNumber) { 229 | this.shippingPhoneNumber = shippingPhoneNumber; 230 | } 231 | public String getFullName() { 232 | return fullName; 233 | } 234 | public void setFullName(final String fullName) { 235 | this.fullName = fullName; 236 | } 237 | public Boolean isEligibleForCardUpdater() { 238 | return eligibleForCardUpdater; 239 | } 240 | public void setEligibleForCardUpdater(final Boolean eligibleForCardUpdater) { 241 | this.eligibleForCardUpdater = eligibleForCardUpdater; 242 | } 243 | public SpreedlyPaymentMethodType getPaymentMethodType() { 244 | return paymentMethodType; 245 | } 246 | public void setPaymentMethodType(final SpreedlyPaymentMethodType paymentMethodType) { 247 | this.paymentMethodType = paymentMethodType; 248 | } 249 | public String getVerificationValue() { 250 | return verificationValue; 251 | } 252 | public void setVerificationValue(final String verificationValue) { 253 | this.verificationValue = verificationValue; 254 | } 255 | public List getErrors() { 256 | return errors; 257 | } 258 | public void setErrors(final List errors) { 259 | this.errors = errors; 260 | } 261 | public SpreedlyApiURLs getApiUrls() { 262 | return apiUrls; 263 | } 264 | public void setApiUrls(final SpreedlyApiURLs apiUrls) { 265 | this.apiUrls = apiUrls; 266 | } 267 | public String getNumber() { 268 | return number; 269 | } 270 | public void setNumber(final String number) { 271 | this.number = number; 272 | } 273 | public String getFingerprint() { 274 | return fingerprint; 275 | } 276 | public void setFingerprint(final String fingerprint) { 277 | this.fingerprint = fingerprint; 278 | } 279 | public String getCompany() 280 | { 281 | return company; 282 | } 283 | public void setCompany(final String company) 284 | { 285 | this.company = company; 286 | } 287 | 288 | 289 | } -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/SpreedlyPaymentMethodState.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model; 2 | 3 | import javax.xml.bind.annotation.XmlEnum; 4 | import javax.xml.bind.annotation.XmlEnumValue; 5 | import javax.xml.bind.annotation.XmlType; 6 | 7 | @XmlType 8 | @XmlEnum(String.class) 9 | public enum SpreedlyPaymentMethodState { 10 | 11 | @XmlEnumValue("cached") CACHED, 12 | @XmlEnumValue("retained") RETAINED, 13 | @XmlEnumValue("redacted") REDACTED 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/SpreedlyPaymentMethodType.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model; 2 | 3 | import javax.xml.bind.annotation.XmlEnum; 4 | import javax.xml.bind.annotation.XmlEnumValue; 5 | import javax.xml.bind.annotation.XmlType; 6 | 7 | @XmlType 8 | @XmlEnum(String.class) 9 | public enum SpreedlyPaymentMethodType { 10 | 11 | @XmlEnumValue("credit_card") CREDIT_CARD, 12 | @XmlEnumValue("bank_account") BANK_ACCOUNT, 13 | @XmlEnumValue("dwolla") DWOLLA, 14 | @XmlEnumValue("paypal") PAYPAL, 15 | @XmlEnumValue("sprel") SPREL, 16 | @XmlEnumValue("third_party_token") THIRD_PARTY_TOKEN, 17 | @XmlEnumValue("apple_pay") APPLE_PAY 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/SpreedlyShippingAddress.java: -------------------------------------------------------------------------------- 1 | 2 | package cc.protea.spreedly.model; 3 | 4 | import javax.xml.bind.annotation.XmlAccessType; 5 | import javax.xml.bind.annotation.XmlAccessorType; 6 | import javax.xml.bind.annotation.XmlElement; 7 | import javax.xml.bind.annotation.XmlRootElement; 8 | 9 | 10 | @XmlRootElement(name = "shipping_address") 11 | @XmlAccessorType(XmlAccessType.FIELD) 12 | public class SpreedlyShippingAddress 13 | { 14 | public String name; 15 | public String address1; 16 | public String address2; 17 | public String city; 18 | public String state; 19 | public String zip; 20 | public String country; 21 | @XmlElement(name = "phone_number") 22 | public String phoneNumber; 23 | 24 | 25 | public String getPhoneNumber() 26 | { 27 | return phoneNumber; 28 | } 29 | 30 | 31 | public void setPhoneNumber(String phoneNumber) 32 | { 33 | this.phoneNumber = phoneNumber; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/SpreedlyStorageState.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model; 2 | 3 | import javax.xml.bind.annotation.XmlEnum; 4 | import javax.xml.bind.annotation.XmlEnumValue; 5 | import javax.xml.bind.annotation.XmlType; 6 | 7 | @XmlType 8 | @XmlEnum(String.class) 9 | public enum SpreedlyStorageState { 10 | 11 | @XmlEnumValue("retained") RETAINED, 12 | @XmlEnumValue("cached") CACHED, 13 | @XmlEnumValue("redacted") REDACTED 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/SpreedlyTransactionRequest.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model; 2 | 3 | import javax.xml.bind.annotation.XmlAccessType; 4 | import javax.xml.bind.annotation.XmlAccessorType; 5 | import javax.xml.bind.annotation.XmlElement; 6 | import javax.xml.bind.annotation.XmlRootElement; 7 | import javax.xml.bind.annotation.XmlTransient; 8 | 9 | @XmlRootElement(name = "transaction") 10 | @XmlAccessorType(XmlAccessType.FIELD) 11 | public class SpreedlyTransactionRequest { 12 | /** 13 | * A unique string generated by Spreedly to identify a gateway. 14 | */ 15 | @XmlTransient public String gatewayAccountToken; 16 | 17 | /** 18 | * A unique string generated by Spreedly to identify a transaction. 19 | */ 20 | @XmlTransient public String referenceTransactionToken; 21 | 22 | /** 23 | * Any positive whole number, for example 1234 = $12.34. 24 | */ 25 | @XmlElement(name = "amount") public Integer amountInCents; 26 | 27 | /** 28 | * ISO 4217 Currency Code e.g., USD, MXN, EUR 29 | */ 30 | @XmlElement(name = "currency_code") public String currencyCode; 31 | 32 | /** 33 | * A unique string generated by Spreedly to identify a payment method. 34 | */ 35 | @XmlElement(name = "payment_method_token") public String paymentMethodToken; 36 | 37 | /** 38 | * Some gateways support specifying your own unique token for third party vaulting using store() 39 | */ 40 | @XmlElement(name = "third_party_token") public String thirdPartyToken; 41 | 42 | /** 43 | * Setting this value to true will make the payment method be saved permanently. Otherwise it will remain in the cached state for three minutes. 44 | */ 45 | @XmlElement(name = "retain_on_success") public boolean retainOnSuccess; 46 | 47 | /** 48 | * A merchant specified tracking number. 49 | */ 50 | @XmlElement(name = "order_id") public String orderId; 51 | 52 | /** 53 | * Description of product or service sold. 54 | */ 55 | public String description; 56 | 57 | /** 58 | * Customer IP address. 59 | */ 60 | @XmlElement(name = "ip") public String clientIpAddress; 61 | 62 | /** 63 | * Customer email address. 64 | */ 65 | public String email; 66 | 67 | /** 68 | * Custom name description that may end up on bank statement, depending on the gateway. 69 | */ 70 | @XmlElement(name = "merchant_name_descriptor") public String merchantNameDescriptor; 71 | 72 | /** 73 | * Custom location description that may end up on bank statement, depending on the gateway. 74 | */ 75 | @XmlElement(name = "merchant_location_descriptor") public String merchantLocationDescriptor; 76 | 77 | /** 78 | * Please see https://docs.spreedly.com/guides/3dsecure/ for usage instructions 79 | */ 80 | @XmlElement(name = "attempt_3dsecure") public Boolean attempt3dSecure = false; 81 | 82 | /** 83 | * Please see https://docs.spreedly.com/guides/3dsecure/ for usage instructions 84 | */ 85 | @XmlElement(name = "redirect_url") public String redirectUrl; 86 | 87 | /** 88 | * The callback url will receive a POST back of all transactions that have changed since the last callback. 89 | * You should respond with a 200 OK response within 5 seconds. If Core does not receive back a 200 response 90 | * within this time, it will retry the callback again at least 4 times at ever-increasing intervals. 91 | */ 92 | @XmlElement(name = "callback_url") public String callbackUrl; 93 | 94 | /** 95 | * @return A unique string generated by Spreedly to identify a gateway. 96 | */ 97 | public String getGatewayAccountToken() { 98 | return gatewayAccountToken; 99 | } 100 | /** 101 | * @param gatewayAccountToken A unique string generated by Spreedly to identify a gateway. 102 | */ 103 | public SpreedlyTransactionRequest setGatewayAccountToken(final String gatewayAccountToken) { 104 | this.gatewayAccountToken = gatewayAccountToken; 105 | return this; 106 | } 107 | 108 | /** 109 | * @return A unique string generated by Spreedly to identify a transaction. 110 | */ 111 | public String getReferenceTransactionToken() { 112 | return referenceTransactionToken; 113 | } 114 | /** 115 | * @param referenceTransactionToken A unique string generated by Spreedly to identify a transaction. 116 | */ 117 | public SpreedlyTransactionRequest setReferenceTransactionToken(final String referenceTransactionToken) { 118 | this.referenceTransactionToken = referenceTransactionToken; 119 | return this; 120 | } 121 | 122 | /** 123 | * @return Any positive whole number, for example 1234 = $12.34. 124 | */ 125 | public Integer getAmountInCents() { 126 | return amountInCents; 127 | } 128 | /** 129 | * @param amountInCents Any positive whole number, for example 1234 = $12.34. 130 | */ 131 | public SpreedlyTransactionRequest setAmountInCents(final Integer amountInCents) { 132 | this.amountInCents = amountInCents; 133 | return this; 134 | } 135 | 136 | /** 137 | * @return ISO 4217 Currency Code e.g., USD, MXN, EUR 138 | */ 139 | public String getCurrencyCode() { 140 | return currencyCode; 141 | } 142 | /** 143 | * @param currencyCode ISO 4217 Currency Code e.g., USD, MXN, EUR 144 | */ 145 | public SpreedlyTransactionRequest setCurrencyCode(final String currencyCode) { 146 | this.currencyCode = currencyCode; 147 | return this; 148 | } 149 | 150 | /** 151 | * Some gateways support specifying your own unique token for third party vaulting using store() 152 | * @return the third party token requested 153 | */ 154 | public String getThirdPartyToken() { 155 | return thirdPartyToken; 156 | } 157 | /** 158 | * Some gateways support specifying your own unique token for third party vaulting using store() 159 | * @param thirdPartyToken the third party token requested 160 | */ 161 | public SpreedlyTransactionRequest setThirdPartyToken(final String thirdPartyToken) { 162 | this.thirdPartyToken = thirdPartyToken; 163 | return this; 164 | } 165 | 166 | /** 167 | * @return A unique string generated by Spreedly to identify a payment method. 168 | */ 169 | public String getPaymentMethodToken() { 170 | return paymentMethodToken; 171 | } 172 | /** 173 | * @param paymentMethodToken A unique string generated by Spreedly to identify a payment method. 174 | */ 175 | public SpreedlyTransactionRequest setPaymentMethodToken(final String paymentMethodToken) { 176 | this.paymentMethodToken = paymentMethodToken; 177 | return this; 178 | } 179 | 180 | /** 181 | * @return True will make the payment method be saved permanently. Otherwise it will remain in the cached state for three minutes. 182 | */ 183 | public boolean isRetainOnSuccess() { 184 | return retainOnSuccess; 185 | } 186 | /** 187 | * @param retainOnSuccess Setting this value to true will make the payment method be saved permanently. Otherwise it will remain in the cached state for three minutes. 188 | */ 189 | public SpreedlyTransactionRequest setRetainOnSuccess(final boolean retainOnSuccess) { 190 | this.retainOnSuccess = retainOnSuccess; 191 | return this; 192 | } 193 | 194 | /** 195 | * @return A merchant specified tracking number. 196 | */ 197 | public String getOrderId() { 198 | return orderId; 199 | } 200 | /** 201 | * @param orderId A merchant specified tracking number. 202 | */ 203 | public SpreedlyTransactionRequest setOrderId(final String orderId) { 204 | this.orderId = orderId; 205 | return this; 206 | } 207 | 208 | /** 209 | * @return Description of product or service sold. 210 | */ 211 | public String getDescription() { 212 | return description; 213 | } 214 | /** 215 | * @param description Description of product or service sold. 216 | */ 217 | public SpreedlyTransactionRequest setDescription(final String description) { 218 | this.description = description; 219 | return this; 220 | } 221 | 222 | /** 223 | * @return Customer IP address. 224 | */ 225 | public String getClientIpAddress() { 226 | return clientIpAddress; 227 | } 228 | /** 229 | * @param clientIpAddress Customer IP address. 230 | */ 231 | public SpreedlyTransactionRequest setClientIpAddress(final String clientIpAddress) { 232 | this.clientIpAddress = clientIpAddress; 233 | return this; 234 | } 235 | 236 | /** 237 | * @return Customer email address. 238 | */ 239 | public String getEmail() { 240 | return email; 241 | } 242 | /** 243 | * @param email Customer email address. 244 | */ 245 | public SpreedlyTransactionRequest setEmail(final String email) { 246 | this.email = email; 247 | return this; 248 | } 249 | 250 | /** 251 | * @return Custom name description that may end up on bank statement, depending on the gateway. 252 | */ 253 | public String getMerchantNameDescriptor() { 254 | return merchantNameDescriptor; 255 | } 256 | /** 257 | * @param merchantNameDescriptor Custom name description that may end up on bank statement, depending on the gateway. 258 | */ 259 | public SpreedlyTransactionRequest setMerchantNameDescriptor(final String merchantNameDescriptor) { 260 | this.merchantNameDescriptor = merchantNameDescriptor; 261 | return this; 262 | } 263 | 264 | /** 265 | * @return Custom location description that may end up on bank statement, depending on the gateway. 266 | */ 267 | public String getMerchantLocationDescriptor() { 268 | return merchantLocationDescriptor; 269 | } 270 | /** 271 | * @param merchantLocationDescriptor Custom location description that may end up on bank statement, depending on the gateway. 272 | */ 273 | public SpreedlyTransactionRequest setMerchantLocationDescriptor(final String merchantLocationDescriptor) { 274 | this.merchantLocationDescriptor = merchantLocationDescriptor; 275 | return this; 276 | } 277 | 278 | /** 279 | * @return if the system should use a multi-stage 3D Secure workflow. See https://docs.spreedly.com/guides/3dsecure/ for instructions. 280 | */ 281 | public boolean isAttempt3dSecure() { 282 | return attempt3dSecure; 283 | } 284 | /** 285 | * @param attempt3dSecure true if the system should use a multi-stage 3D Secure workflow. See https://docs.spreedly.com/guides/3dsecure/ for instructions. 286 | */ 287 | public void setAttempt3dSecure(final boolean attempt3dSecure) { 288 | this.attempt3dSecure = attempt3dSecure; 289 | } 290 | /** 291 | * @return See https://docs.spreedly.com/guides/3dsecure/ for instructions. 292 | */ 293 | public String getRedirectUrl() { 294 | return redirectUrl; 295 | } 296 | /** 297 | * @param redirectUrl See https://docs.spreedly.com/guides/3dsecure/ for instructions. 298 | */ 299 | public void setRedirectUrl(final String redirectUrl) { 300 | this.redirectUrl = redirectUrl; 301 | } 302 | /** 303 | * The callback url will receive a POST back of all transactions that have changed since the last callback. 304 | * You should respond with a 200 OK response within 5 seconds. If Core does not receive back a 200 response within this time, 305 | * it will retry the callback again at least 4 times at ever-increasing intervals. 306 | * @return The callback url 307 | */ 308 | public String getCallbackUrl() { 309 | return callbackUrl; 310 | } 311 | /** 312 | * The callback url will receive a POST back of all transactions that have changed since the last callback. 313 | * You should respond with a 200 OK response within 5 seconds. If Core does not receive back a 200 response within this time, 314 | * it will retry the callback again at least 4 times at ever-increasing intervals. 315 | * @param callbackUrl 316 | */ 317 | public void setCallbackUrl(final String callbackUrl) { 318 | this.callbackUrl = callbackUrl; 319 | } 320 | 321 | 322 | 323 | } 324 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/SpreedlyTransactionResponse.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model; 2 | 3 | import java.util.Date; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | import javax.xml.bind.annotation.XmlAccessType; 8 | import javax.xml.bind.annotation.XmlAccessorType; 9 | import javax.xml.bind.annotation.XmlElement; 10 | import javax.xml.bind.annotation.XmlRootElement; 11 | import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 12 | 13 | import cc.protea.spreedly.model.internal.SpreedlyErrorSetting; 14 | import cc.protea.spreedly.model.internal.SpreedlyNestedMapAdapter; 15 | 16 | @XmlRootElement(name = "transaction") 17 | @XmlAccessorType(XmlAccessType.FIELD) 18 | public class SpreedlyTransactionResponse implements SpreedlyErrorSetting { 19 | 20 | /** 21 | * Any positive whole number, for example 1234 = $12.34. 22 | */ 23 | @XmlElement(name = "amount") public Integer amountInCents; 24 | /** 25 | * Value is true if run on a Test Gateway. 26 | */ 27 | @XmlElement(name = "on_test_gateway") public boolean onTestGateway; 28 | /** 29 | * Date and time of origination. 30 | */ 31 | @XmlElement(name = "created_at") public Date createdOn; 32 | /** 33 | * Date and time of modification. 34 | */ 35 | @XmlElement(name = "updated_at") public Date updatedOn; 36 | /** 37 | * ISO 4217 Currency Code e.g., USD, MXN, EUR 38 | */ 39 | @XmlElement(name = "currency_code") public String currencyCode; 40 | /** 41 | * true if transaction was successful. 42 | */ 43 | public boolean succeeded; 44 | /** 45 | * The state of the transaction. 46 | */ 47 | public SpreedlyTransactionState state; 48 | /** 49 | * A unique string generated by Spreedly to identify a transaction. 50 | */ 51 | public String token; 52 | /** 53 | * The type of transaction. 54 | */ 55 | @XmlElement(name = "transaction_type") public SpreedlyTransactionType transactionType; 56 | /** 57 | * A tracking number that you can declare. If you don't specify an orderId, we'll pass the token of the transaction as the orderId. 58 | */ 59 | @XmlElement(name = "order_id") public String orderId; 60 | /** 61 | * IP address of the customer making the purchase. 62 | */ 63 | @XmlElement(name = "ip") public String clientIpAddress; 64 | /** 65 | * Description of the product or service rendered. 66 | */ 67 | public String description; 68 | /** 69 | * Customer email address. 70 | */ 71 | public String email; 72 | /** 73 | * Name of merchant. 74 | */ 75 | @XmlElement(name = "merchant_name_descriptor") public String merchantNameDescriptor; 76 | /** 77 | * Location of merchant. 78 | */ 79 | @XmlElement(name = "merchant_location_descriptor") public String merchantLocationDescriptor; 80 | /** 81 | * Fields that a gateway defines for a specific purpose but are not implemented by all gateways. 82 | */ 83 | @XmlJavaTypeAdapter(SpreedlyNestedMapAdapter.class) 84 | @XmlElement(name = "gateway_specific_fields") public Map gatewaySpecificFields = new HashMap(); 85 | @XmlJavaTypeAdapter(SpreedlyNestedMapAdapter.class) 86 | @XmlElement(name = "gateway_specific_response_fields") public Map gatewaySpecificResponseFields = new HashMap(); 87 | @XmlElement(name = "gateway_transaction_id") public String gatewayTransactionId; 88 | @XmlElement(name = "gateway_latency_ms") public String gatewayLatencyMs; 89 | @XmlElement(name = "retain_on_success") public boolean retainOnSuccess; 90 | @XmlElement(name = "payment_method_added") public boolean paymentMethodAdded; 91 | public SpreedlyMessage message; 92 | @XmlElement(name = "gateway_token") public String gatewayToken; 93 | @XmlElement(name = "shipping_address") public SpreedlyShippingAddress shippingAddress; 94 | public SpreedlyTransactionResponseResponse response; 95 | @XmlElement(name = "payment_method") public SpreedlyPaymentMethod paymentMethod; 96 | @XmlElement(name = "basis_payment_method") public SpreedlyPaymentMethod basisPaymentMethod; 97 | @XmlElement(name = "api_urls") public SpreedlyApiURLs apiUrls; 98 | /** 99 | * The callbackUrl specified when the transaction was created 100 | */ 101 | @XmlElement(name = "callback_url") public String callbackUrl; 102 | /** 103 | * The redirectUrl specified when the transaction was created 104 | */ 105 | @XmlElement(name = "redirect_url") public String redirectUrl; 106 | /** 107 | * If a checkoutUrl is returned, you need to redirect the customer's browser to it. Doing so will land the customer on the offsite page they will use to authorize payment. 108 | * See https://docs.spreedly.com/guides/3dsecure/ for more information. 109 | */ 110 | @XmlElement(name = "checkout_url") public String checkoutUrl; 111 | 112 | /** 113 | * If a checkoutForm is returned, you need to render and submit it. You can also parse it (it is always a valid XHTML fragment) and build your own form with the same action and input fields. 114 | * See https://docs.spreedly.com/guides/3dsecure/ for more information. 115 | */ 116 | @XmlElement(name = "checkout_form") public String checkoutForm; 117 | @XmlElement(name = "setup_response") public SpreedlyTransactionResponseDetails setupResponse; 118 | @XmlElement(name = "redirect_response") public SpreedlyTransactionResponseDetails redirectResponse; 119 | @XmlElement(name = "callback_response") public SpreedlyTransactionResponseDetails callbackResponse; 120 | 121 | /** 122 | * @return Any positive whole number, for example 1234 = $12.34. 123 | */ 124 | public Integer getAmountInCents() { 125 | return amountInCents; 126 | } 127 | /** 128 | * @param amountInCents Any positive whole number, for example 1234 = $12.34. 129 | */ 130 | public SpreedlyTransactionResponse setAmountInCents(final Integer amountInCents) { 131 | this.amountInCents = amountInCents; 132 | return this; 133 | } 134 | 135 | /** 136 | * @return true if run on a Test Gateway. 137 | */ 138 | public boolean isOnTestGateway() { 139 | return onTestGateway; 140 | } 141 | /** 142 | * @param onTestGateway true if run on a Test Gateway. 143 | */ 144 | public SpreedlyTransactionResponse setOnTestGateway(final boolean onTestGateway) { 145 | this.onTestGateway = onTestGateway; 146 | return this; 147 | } 148 | 149 | /** 150 | * @return Date and time of origination. 151 | */ 152 | public Date getCreatedOn() { 153 | return createdOn; 154 | } 155 | /** 156 | * @param createdOn Date and time of origination. 157 | */ 158 | public SpreedlyTransactionResponse setCreatedOn(final Date createdOn) { 159 | this.createdOn = createdOn; 160 | return this; 161 | } 162 | 163 | /** 164 | * @return Date and time of modification. 165 | */ 166 | public Date getUpdatedOn() { 167 | return updatedOn; 168 | } 169 | /** 170 | * @param updatedOn Date and time of modification. 171 | */ 172 | public SpreedlyTransactionResponse setUpdatedOn(final Date updatedOn) { 173 | this.updatedOn = updatedOn; 174 | return this; 175 | } 176 | 177 | /** 178 | * @return ISO 4217 Currency Code e.g., USD, MXN, EUR 179 | */ 180 | public String getCurrencyCode() { 181 | return currencyCode; 182 | } 183 | /** 184 | * @param currencyCode ISO 4217 Currency Code e.g., USD, MXN, EUR 185 | */ 186 | public SpreedlyTransactionResponse setCurrencyCode(final String currencyCode) { 187 | this.currencyCode = currencyCode; 188 | return this; 189 | } 190 | 191 | /** 192 | * @return true if transaction was successful. 193 | */ 194 | public boolean isSucceeded() { 195 | return succeeded; 196 | } 197 | /** 198 | * @param succeeded true if transaction was successful. 199 | */ 200 | public SpreedlyTransactionResponse setSucceeded(final boolean succeeded) { 201 | this.succeeded = succeeded; 202 | return this; 203 | } 204 | 205 | /** 206 | * @return The state of the transaction. 207 | */ 208 | public SpreedlyTransactionState getState() { 209 | return state; 210 | } 211 | /** 212 | * @param state The state of the transaction. 213 | */ 214 | public SpreedlyTransactionResponse setState(final SpreedlyTransactionState state) { 215 | this.state = state; 216 | return this; 217 | } 218 | 219 | /** 220 | * @return A unique string generated by Spreedly to identify a transaction. 221 | */ 222 | public String getToken() { 223 | return token; 224 | } 225 | /** 226 | * @param token A unique string generated by Spreedly to identify a transaction. 227 | */ 228 | public SpreedlyTransactionResponse setToken(final String token) { 229 | this.token = token; 230 | return this; 231 | } 232 | 233 | /** 234 | * @return The type of transaction. 235 | */ 236 | public SpreedlyTransactionType getTransactionType() { 237 | return transactionType; 238 | } 239 | /** 240 | * @param transactionType The type of transaction. 241 | */ 242 | public SpreedlyTransactionResponse setTransactionType(final SpreedlyTransactionType transactionType) { 243 | this.transactionType = transactionType; 244 | return this; 245 | } 246 | 247 | /** 248 | * @return A tracking number that you can declare. If you don't specify an orderId, we'll pass the token of the transaction as the orderId. 249 | */ 250 | public String getOrderId() { 251 | return orderId; 252 | } 253 | /** 254 | * @param orderId A tracking number that you can declare. If you don't specify an orderId, we'll pass the token of the transaction as the orderId. 255 | */ 256 | public SpreedlyTransactionResponse setOrderId(final String orderId) { 257 | this.orderId = orderId; 258 | return this; 259 | } 260 | 261 | /** 262 | * @return IP address of the customer making the purchase. 263 | */ 264 | public String getClientIpAddress() { 265 | return clientIpAddress; 266 | } 267 | /** 268 | * @param clientIpAddress IP address of the customer making the purchase. 269 | */ 270 | public SpreedlyTransactionResponse setClientIpAddress(final String clientIpAddress) { 271 | this.clientIpAddress = clientIpAddress; 272 | return this; 273 | } 274 | 275 | /** 276 | * @return Description of the product or service rendered. 277 | */ 278 | public String getDescription() { 279 | return description; 280 | } 281 | /** 282 | * @param description Description of the product or service rendered. 283 | */ 284 | public SpreedlyTransactionResponse setDescription(final String description) { 285 | this.description = description; 286 | return this; 287 | } 288 | 289 | /** 290 | * @return Customer email address. 291 | */ 292 | public String getEmail() { 293 | return email; 294 | } 295 | /** 296 | * @param email Customer email address. 297 | */ 298 | public SpreedlyTransactionResponse setEmail(final String email) { 299 | this.email = email; 300 | return this; 301 | } 302 | /** 303 | * @return Name of merchant. 304 | */ 305 | public String getMerchantNameDescriptor() { 306 | return merchantNameDescriptor; 307 | } 308 | /** 309 | * @param merchantNameDescriptor Name of merchant. 310 | */ 311 | public SpreedlyTransactionResponse setMerchantNameDescriptor(final String merchantNameDescriptor) { 312 | this.merchantNameDescriptor = merchantNameDescriptor; 313 | return this; 314 | } 315 | 316 | /** 317 | * @return Location of merchant. 318 | */ 319 | public String getMerchantLocationDescriptor() { 320 | return merchantLocationDescriptor; 321 | } 322 | /** 323 | * @param merchantLocationDescriptor Location of merchant. 324 | */ 325 | public SpreedlyTransactionResponse setMerchantLocationDescriptor(final String merchantLocationDescriptor) { 326 | this.merchantLocationDescriptor = merchantLocationDescriptor; 327 | return this; 328 | } 329 | 330 | /** 331 | * @return Fields that a gateway defines for a specific purpose but is not implemented by all gateways. 332 | */ 333 | public Map getGatewaySpecificFields() { 334 | return gatewaySpecificFields; 335 | } 336 | /** 337 | * @param gatewaySpecificFields Fields that a gateway defines for a specific purpose but is not implemented by all gateways. 338 | */ 339 | public SpreedlyTransactionResponse setGatewaySpecificFields(final Map gatewaySpecificFields) { 340 | this.gatewaySpecificFields = gatewaySpecificFields; 341 | return this; 342 | } 343 | 344 | public Map getGatewaySpecificResponseFields() { 345 | return gatewaySpecificResponseFields; 346 | } 347 | public SpreedlyTransactionResponse setGatewaySpecificResponseFields(final Map gatewaySpecificResponseFields) { 348 | this.gatewaySpecificResponseFields = gatewaySpecificResponseFields; 349 | return this; 350 | } 351 | 352 | public String getGatewayTransactionId() { 353 | return gatewayTransactionId; 354 | } 355 | public SpreedlyTransactionResponse setGatewayTransactionId(final String gatewayTransactionId) { 356 | this.gatewayTransactionId = gatewayTransactionId; 357 | return this; 358 | } 359 | 360 | public boolean isRetainOnSuccess() { 361 | return retainOnSuccess; 362 | } 363 | public SpreedlyTransactionResponse setRetainOnSuccess(final boolean retainOnSuccess) { 364 | this.retainOnSuccess = retainOnSuccess; 365 | return this; 366 | } 367 | 368 | public boolean isPaymentMethodAdded() { 369 | return paymentMethodAdded; 370 | } 371 | public SpreedlyTransactionResponse setPaymentMethodAdded(final boolean paymentMethodAdded) { 372 | this.paymentMethodAdded = paymentMethodAdded; 373 | return this; 374 | } 375 | 376 | public SpreedlyMessage getMessage() { 377 | return message; 378 | } 379 | public SpreedlyTransactionResponse setMessage(final SpreedlyMessage message) { 380 | this.message = message; 381 | return this; 382 | } 383 | 384 | public String getGatewayToken() { 385 | return gatewayToken; 386 | } 387 | public SpreedlyTransactionResponse setGatewayToken(final String gatewayToken) { 388 | this.gatewayToken = gatewayToken; 389 | return this; 390 | } 391 | 392 | public SpreedlyTransactionResponseResponse getResponse() { 393 | return response; 394 | } 395 | public SpreedlyTransactionResponse setResponse(final SpreedlyTransactionResponseResponse response) { 396 | this.response = response; 397 | return this; 398 | } 399 | 400 | public SpreedlyPaymentMethod getPaymentMethod() { 401 | return paymentMethod; 402 | } 403 | public SpreedlyTransactionResponse setPaymentMethod(final SpreedlyPaymentMethod paymentMethod) { 404 | this.paymentMethod = paymentMethod; 405 | return this; 406 | } 407 | 408 | public SpreedlyPaymentMethod getBasisPaymentMethod() { 409 | return basisPaymentMethod; 410 | } 411 | public SpreedlyTransactionResponse setBasisPaymentMethod(final SpreedlyPaymentMethod basisPaymentMethod) { 412 | this.basisPaymentMethod = basisPaymentMethod; 413 | return this; 414 | } 415 | 416 | public SpreedlyApiURLs getApiUrls() { 417 | return apiUrls; 418 | } 419 | public SpreedlyTransactionResponse setApiUrls(final SpreedlyApiURLs apiUrls) { 420 | this.apiUrls = apiUrls; 421 | return this; 422 | } 423 | 424 | /** 425 | * @return the callbackUrl specified when the transaction was created 426 | */ 427 | public String getCallbackUrl() { 428 | return callbackUrl; 429 | } 430 | /** 431 | * @param callbackUrl the callbackUrl specified when the transaction was created 432 | */ 433 | public SpreedlyTransactionResponse setCallbackUrl(final String callbackUrl) { 434 | this.callbackUrl = callbackUrl; 435 | return this; 436 | } 437 | 438 | /** 439 | * @return the redirectUrl specified when the transaction was created 440 | */ 441 | public String getRedirectUrl() { 442 | return redirectUrl; 443 | } 444 | /** 445 | * @param redirectUrl the redirectUrl specified when the transaction was created 446 | */ 447 | public SpreedlyTransactionResponse setRedirectUrl(final String redirectUrl) { 448 | this.redirectUrl = redirectUrl; 449 | return this; 450 | } 451 | 452 | /** 453 | * If a checkoutUrl is returned, you need to redirect the customer's browser to it. Doing so will land the customer on the offsite 454 | * page they will use to authorize payment. 455 | * @return the checkout URL 456 | */ 457 | public String getCheckoutUrl() { 458 | return checkoutUrl; 459 | } 460 | /** 461 | * If a checkoutUrl is returned, you need to redirect the customer's browser to it. Doing so will land the customer on the offsite 462 | * page they will use to authorize payment. 463 | * @param checkoutUrl 464 | */ 465 | public SpreedlyTransactionResponse setCheckoutUrl(final String checkoutUrl) { 466 | this.checkoutUrl = checkoutUrl; 467 | return this; 468 | } 469 | 470 | /** 471 | * If a checkoutForm is returned, you need to render and submit it. You can also parse it (it is always a valid XHTML fragment) and 472 | * build your own form with the same action and input fields. 473 | * See https://docs.spreedly.com/guides/3dsecure/ for more information. 474 | * @return the checkoutForm HTML code 475 | */ 476 | public String getCheckoutForm() { 477 | return checkoutForm; 478 | } 479 | /** 480 | * If a checkoutForm is returned, you need to render and submit it. You can also parse it (it is always a valid XHTML fragment) and 481 | * build your own form with the same action and input fields. 482 | * See https://docs.spreedly.com/guides/3dsecure/ for more information. 483 | * @param checkoutForm 484 | */ 485 | public SpreedlyTransactionResponse setCheckoutForm(final String checkoutForm) { 486 | this.checkoutForm = checkoutForm; 487 | return this; 488 | } 489 | 490 | public SpreedlyTransactionResponseDetails getSetupResponse() { 491 | return setupResponse; 492 | } 493 | public SpreedlyTransactionResponse setSetupResponse(final SpreedlyTransactionResponseDetails setupResponse) { 494 | this.setupResponse = setupResponse; 495 | return this; 496 | } 497 | public SpreedlyTransactionResponseDetails getRedirectResponse() { 498 | return redirectResponse; 499 | } 500 | public SpreedlyTransactionResponse setRedirectResponse(final SpreedlyTransactionResponseDetails redirectResponse) { 501 | this.redirectResponse = redirectResponse; 502 | return this; 503 | } 504 | public SpreedlyTransactionResponseDetails getCallbackResponse() { 505 | return callbackResponse; 506 | } 507 | public SpreedlyTransactionResponse setCallbackResponse(final SpreedlyTransactionResponseDetails callbackResponse) { 508 | this.callbackResponse = callbackResponse; 509 | return this; 510 | } 511 | 512 | public void setError(final String key, final String error) { 513 | message = new SpreedlyMessage(); 514 | message.key = key; 515 | message.message = error; 516 | this.succeeded = false; 517 | } 518 | 519 | public String getGatewayLatencyMs() 520 | { 521 | return gatewayLatencyMs; 522 | } 523 | public SpreedlyTransactionResponse setGatewayLatencyMs(String gatewayLatencyMs) 524 | { 525 | this.gatewayLatencyMs = gatewayLatencyMs; 526 | return this; 527 | } 528 | public SpreedlyShippingAddress getShippingAddress() 529 | { 530 | return shippingAddress; 531 | } 532 | public SpreedlyTransactionResponse setShippingAddress(SpreedlyShippingAddress shippingAddress) 533 | { 534 | this.shippingAddress = shippingAddress; 535 | return this; 536 | } 537 | 538 | } 539 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/SpreedlyTransactionResponseDetails.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model; 2 | 3 | import java.util.Date; 4 | 5 | import javax.xml.bind.annotation.XmlAccessType; 6 | import javax.xml.bind.annotation.XmlAccessorType; 7 | import javax.xml.bind.annotation.XmlElement; 8 | 9 | @XmlAccessorType(XmlAccessType.FIELD) 10 | public class SpreedlyTransactionResponseDetails { 11 | 12 | public boolean success; 13 | public SpreedlyMessage message; 14 | @XmlElement(name = "error_code") public String errorCode; 15 | @XmlElement(name = "checkout_url") public String checkoutUrl; 16 | /** 17 | * Date and time of origination. 18 | */ 19 | @XmlElement(name = "created_at") public Date createdOn; 20 | /** 21 | * Date and time of modification. 22 | */ 23 | @XmlElement(name = "updated_at") public Date updatedOn; 24 | 25 | public boolean isSuccess() { 26 | return success; 27 | } 28 | public void setSuccess(final boolean success) { 29 | this.success = success; 30 | } 31 | public SpreedlyMessage getMessage() { 32 | return message; 33 | } 34 | public void setMessage(final SpreedlyMessage message) { 35 | this.message = message; 36 | } 37 | public String getErrorCode() { 38 | return errorCode; 39 | } 40 | public void setErrorCode(final String errorCode) { 41 | this.errorCode = errorCode; 42 | } 43 | public String getCheckoutUrl() { 44 | return checkoutUrl; 45 | } 46 | public void setCheckoutUrl(final String checkoutUrl) { 47 | this.checkoutUrl = checkoutUrl; 48 | } 49 | public Date getCreatedOn() { 50 | return createdOn; 51 | } 52 | public void setCreatedOn(final Date createdOn) { 53 | this.createdOn = createdOn; 54 | } 55 | public Date getUpdatedOn() { 56 | return updatedOn; 57 | } 58 | public void setUpdatedOn(final Date updatedOn) { 59 | this.updatedOn = updatedOn; 60 | } 61 | 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/SpreedlyTransactionResponseResponse.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model; 2 | 3 | import java.util.Date; 4 | 5 | import javax.xml.bind.annotation.XmlAccessType; 6 | import javax.xml.bind.annotation.XmlAccessorType; 7 | import javax.xml.bind.annotation.XmlElement; 8 | 9 | @XmlAccessorType(XmlAccessType.FIELD) 10 | public class SpreedlyTransactionResponseResponse { 11 | 12 | public boolean success; 13 | public SpreedlyMessage message; 14 | @XmlElement(name = "avs_code") public SpreedlyAvsResponse avsResponse; 15 | @XmlElement(name = "avs_message") public String avsMessage; 16 | @XmlElement(name = "cvv_code") public SpreedlyCvvResponse cvvResponse; 17 | @XmlElement(name = "cvv_message") public String cvvMessage; 18 | public boolean pending; 19 | @XmlElement(name = "error_code") public String errorCode; 20 | @XmlElement(name = "error_detail") public String errorDetail; 21 | public boolean cancelled; 22 | /** 23 | * Date and time of origination. 24 | */ 25 | @XmlElement(name = "created_at") public Date createdOn; 26 | /** 27 | * Date and time of modification. 28 | */ 29 | @XmlElement(name = "updated_at") public Date updatedOn; 30 | @XmlElement(name = "result_unknown") public String resultUnknown; 31 | @XmlElement(name = "fraud_review") public String fraudReview; 32 | 33 | } -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/SpreedlyTransactionState.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model; 2 | 3 | import javax.xml.bind.annotation.XmlEnum; 4 | import javax.xml.bind.annotation.XmlEnumValue; 5 | import javax.xml.bind.annotation.XmlType; 6 | 7 | @XmlType 8 | @XmlEnum(String.class) 9 | public enum SpreedlyTransactionState { 10 | 11 | /** 12 | * The transaction has succeeded and funds have been received. 13 | */ 14 | @XmlEnumValue("succeeded") SUCCEEDED, 15 | /** 16 | * The transaction has been accepted. Funds have not yet been received. 17 | */ 18 | @XmlEnumValue("processing") PROCESSING, 19 | /** 20 | * The transaction needs further processing which typically involves redirecting the 21 | * customer to a redirect_url to allow them to specify a payment method. 22 | */ 23 | @XmlEnumValue("pending") PENDING, 24 | /** 25 | * The transaction failed. This could be caused by a number of things such as the payment method 26 | * not being valid, the payment method being redacted, etc. 27 | */ 28 | @XmlEnumValue("failed") FAILED, 29 | /** 30 | * The transaction failed because the attempt to setup the transaction on the offsite gateway failed. 31 | */ 32 | @XmlEnumValue("gateway_setup_failed") GATEWAY_SETUP_FAILED, 33 | /** 34 | * The transaction failed because the gateway declined the charge for some reason. 35 | */ 36 | @XmlEnumValue("gateway_processing_failed") GATEWAY_PROCESSING_FAILED, 37 | /** 38 | * We had difficulty communicating with the service and we're unsure what the result 39 | * of the operation was. (timeouts, connection errors, etc). 40 | */ 41 | @XmlEnumValue("gateway_processing_result_unknown") GATEWAY_PROCESSING_RESULT_UNKNOWN 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/SpreedlyTransactionType.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model; 2 | 3 | import javax.xml.bind.annotation.XmlEnum; 4 | import javax.xml.bind.annotation.XmlEnumValue; 5 | import javax.xml.bind.annotation.XmlType; 6 | 7 | @XmlType 8 | @XmlEnum(String.class) 9 | public enum SpreedlyTransactionType { 10 | 11 | @XmlEnumValue("Authorization") AUTHORIZATION, 12 | @XmlEnumValue("Capture") CAPTURE, 13 | @XmlEnumValue("Credit") CREDIT, 14 | @XmlEnumValue("RedactGateway") REDACT_GATEWAY, 15 | @XmlEnumValue("RecacheSensitiveData") RECACHE_SENSITIVE_DATA, 16 | @XmlEnumValue("Verification") VERIFICATION 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/internal/SpreedlyError.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model.internal; 2 | 3 | import javax.xml.bind.annotation.XmlAccessType; 4 | import javax.xml.bind.annotation.XmlValue; 5 | import javax.xml.bind.annotation.XmlAccessorType; 6 | import javax.xml.bind.annotation.XmlAttribute; 7 | 8 | @XmlAccessorType(XmlAccessType.FIELD) 9 | public class SpreedlyError { 10 | @XmlValue public String error; 11 | @XmlAttribute(name = "key") public String key; 12 | @XmlAttribute(name = "attribute") public String attribute; 13 | } 14 | 15 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/internal/SpreedlyErrorHash.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model.internal; 2 | 3 | import javax.xml.bind.annotation.XmlRootElement; 4 | 5 | @XmlRootElement(name = "hash") 6 | public class SpreedlyErrorHash { 7 | 8 | public String status; 9 | public String error; 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/internal/SpreedlyErrorSetting.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model.internal; 2 | 3 | 4 | public interface SpreedlyErrorSetting { 5 | 6 | public void setError(String key, String error); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/internal/SpreedlyErrors.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model.internal; 2 | 3 | import javax.xml.bind.annotation.XmlElement; 4 | import javax.xml.bind.annotation.XmlRootElement; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | @XmlRootElement(name = "errors") 9 | public class SpreedlyErrors { 10 | @XmlElement(name = "error") public List errors = new ArrayList(); 11 | } 12 | 13 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/internal/SpreedlyGatewayAccountResponse.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model.internal; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import javax.xml.bind.annotation.XmlElement; 7 | import javax.xml.bind.annotation.XmlRootElement; 8 | 9 | import cc.protea.spreedly.model.SpreedlyGatewayAccount; 10 | 11 | @XmlRootElement(name = "gateways") 12 | public class SpreedlyGatewayAccountResponse { 13 | 14 | @XmlElement(name = "gateway") 15 | public List gateways = new ArrayList(); 16 | 17 | } -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/internal/SpreedlyGatewayAccountUpdate.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model.internal; 2 | 3 | import cc.protea.spreedly.model.SpreedlyGatewayAccount; 4 | import cc.protea.spreedly.model.SpreedlyGatewayCredential; 5 | 6 | import javax.xml.bind.annotation.XmlAnyElement; 7 | import javax.xml.bind.annotation.XmlElement; 8 | import javax.xml.bind.annotation.XmlRootElement; 9 | import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 10 | import javax.xml.parsers.DocumentBuilder; 11 | import javax.xml.parsers.DocumentBuilderFactory; 12 | import javax.xml.parsers.ParserConfigurationException; 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | @XmlRootElement(name = "gateway") 17 | public class SpreedlyGatewayAccountUpdate { 18 | 19 | DocumentBuilder documentBuilder; 20 | 21 | public SpreedlyGatewayAccountUpdate() { 22 | try { 23 | documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); 24 | } catch (ParserConfigurationException e) { 25 | e.printStackTrace(); 26 | } 27 | } 28 | 29 | public SpreedlyGatewayAccountUpdate(final SpreedlyGatewayAccount in) { 30 | this.gatewayType = in.gatewayType; 31 | for (SpreedlyGatewayCredential credential : in.credentials) { 32 | SpreedlyInternalKeyValuePair pair = new SpreedlyInternalKeyValuePair(); 33 | pair.key = credential.name; 34 | pair.value = credential.value; 35 | credentials.add(pair); 36 | } 37 | } 38 | 39 | @XmlElement(name = "gateway_type") 40 | public String gatewayType; 41 | 42 | // @XmlElementWrapper(name = "credentials") 43 | @XmlAnyElement 44 | @XmlJavaTypeAdapter(SpreedlyInternalKeyValuePairAdapter.class) 45 | public List credentials = new ArrayList(); 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/internal/SpreedlyGatewayProviderResponse.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model.internal; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import javax.xml.bind.annotation.XmlElement; 7 | import javax.xml.bind.annotation.XmlRootElement; 8 | 9 | import cc.protea.spreedly.model.SpreedlyGatewayProvider; 10 | 11 | @XmlRootElement(name = "gateways") 12 | public class SpreedlyGatewayProviderResponse { 13 | 14 | @XmlElement(name = "gateway") 15 | public List gateways = new ArrayList(); 16 | 17 | } -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/internal/SpreedlyInternalKeyValuePair.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model.internal; 2 | 3 | import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 4 | 5 | @XmlJavaTypeAdapter(SpreedlyInternalKeyValuePairAdapter.class) 6 | public class SpreedlyInternalKeyValuePair { 7 | 8 | public String key; 9 | public String value; 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/internal/SpreedlyInternalKeyValuePairAdapter.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model.internal; 2 | 3 | import org.w3c.dom.Document; 4 | import org.w3c.dom.Element; 5 | 6 | import javax.xml.bind.JAXBContext; 7 | import javax.xml.bind.JAXBElement; 8 | import javax.xml.bind.Marshaller; 9 | import javax.xml.bind.Unmarshaller; 10 | import javax.xml.bind.annotation.adapters.XmlAdapter; 11 | import javax.xml.namespace.QName; 12 | import javax.xml.parsers.DocumentBuilder; 13 | import javax.xml.parsers.DocumentBuilderFactory; 14 | import javax.xml.transform.dom.DOMSource; 15 | 16 | public class SpreedlyInternalKeyValuePairAdapter extends XmlAdapter { 17 | 18 | private DocumentBuilder documentBuilder; 19 | private JAXBContext jaxbContext; 20 | 21 | public SpreedlyInternalKeyValuePairAdapter() { 22 | } 23 | 24 | public SpreedlyInternalKeyValuePairAdapter(JAXBContext jaxbContext) { 25 | this(); 26 | this.jaxbContext = jaxbContext; 27 | } 28 | 29 | private DocumentBuilder getDocumentBuilder() throws Exception { 30 | // Lazy load the DocumentBuilder as it is not used for unmarshalling. 31 | if (null == documentBuilder) { 32 | DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 33 | documentBuilder = dbf.newDocumentBuilder(); 34 | } 35 | return documentBuilder; 36 | } 37 | 38 | private JAXBContext getJAXBContext(Class type) throws Exception { 39 | if (null == jaxbContext) { 40 | // A JAXBContext was not set, so create a new one based on the type. 41 | return JAXBContext.newInstance(type); 42 | } 43 | return jaxbContext; 44 | } 45 | 46 | @Override 47 | public SpreedlyInternalKeyValuePair unmarshal(Object object) throws Exception { 48 | if (null == object) { 49 | return null; 50 | } 51 | 52 | Element element = (Element) object; 53 | 54 | // 2. Unmarshal the element based on the value's type. 55 | DOMSource source = new DOMSource(element); 56 | Unmarshaller unmarshaller = getJAXBContext(String.class).createUnmarshaller(); 57 | JAXBElement jaxbElement = unmarshaller.unmarshal(source, String.class); 58 | 59 | // 3. Build the instance of Parameter 60 | SpreedlyInternalKeyValuePair keyValuePair = new SpreedlyInternalKeyValuePair(); 61 | keyValuePair.key = element.getLocalName(); 62 | keyValuePair.value = jaxbElement.getValue() == null ? null : jaxbElement.getValue().toString(); 63 | return keyValuePair; 64 | } 65 | 66 | @Override 67 | public Object marshal(SpreedlyInternalKeyValuePair keyValuePair) throws Exception { 68 | if (null == keyValuePair) { 69 | return null; 70 | } 71 | 72 | // 1. Build the JAXBElement to wrap the instance of Parameter. 73 | QName rootElement = new QName(keyValuePair.key); 74 | JAXBElement jaxbElement = new JAXBElement(rootElement, String.class, keyValuePair.value); 75 | 76 | // 2. Marshal the JAXBElement to a DOM element. 77 | Document document = getDocumentBuilder().newDocument(); 78 | Marshaller marshaller = getJAXBContext(String.class).createMarshaller(); 79 | // marshaller.setAdapter(SpreedlyInternalKeyValuePairAdapter); 80 | marshaller.marshal(jaxbElement, document); 81 | 82 | Element element = document.getDocumentElement(); 83 | 84 | 85 | // // 3. Set the type attribute based on the value's type. 86 | // element.setAttribute("type", type.getName()); 87 | return element; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/internal/SpreedlyNestedMapAdapter.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model.internal; 2 | 3 | import org.w3c.dom.Element; 4 | import org.w3c.dom.Node; 5 | import org.w3c.dom.NodeList; 6 | 7 | import javax.xml.bind.annotation.adapters.XmlAdapter; 8 | import javax.xml.parsers.DocumentBuilder; 9 | import javax.xml.parsers.DocumentBuilderFactory; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | 14 | /** 15 | * Spreedly sometimes returns an element containing (probably only one) elements that contain effectively random key/value pairs as <key>value<key>. The name of the 16 | * wrapping element is unknown and generally corresponds to the gateway, but new gateways may be added at any time. The data is also unknown and may change over time. 17 | * @author rjstanford 18 | * 19 | */ 20 | public class SpreedlyNestedMapAdapter extends XmlAdapter> { 21 | 22 | @Override 23 | public Map unmarshal(final Object domTree) throws Exception { 24 | if (domTree == null) { 25 | return null; 26 | } 27 | // The 'content' should be 'gateway_specific_response_fields' 28 | Element gatewaySpecificResponseFields = (Element) domTree; 29 | Map map = new HashMap(); 30 | // We are expecting to get zero or more direct children (with unknown names) 31 | NodeList gateways = gatewaySpecificResponseFields.getChildNodes(); 32 | if (gateways == null || gateways.getLength() == 0) { 33 | return null; 34 | } 35 | for (int i = 0; i < gateways.getLength(); ++i) { 36 | Node gateway = gateways.item(i); 37 | if (gateway == null) { 38 | continue; 39 | } 40 | // Each gateway should have zero or more direct children (with unknown but useful names) 41 | NodeList responseFields = gateway.getChildNodes(); 42 | if (responseFields == null) { 43 | continue; 44 | } 45 | for (int j = 0; j < responseFields.getLength(); ++j) { 46 | Node responseField = responseFields.item(j); 47 | if (responseField == null) { 48 | continue; 49 | } 50 | if (responseField.getNodeType() == Node.TEXT_NODE) { 51 | continue; 52 | } 53 | if (! responseField.hasChildNodes()) { 54 | continue; 55 | } 56 | String key = responseField.getNodeName(); 57 | String value = responseField.getFirstChild().getNodeValue(); 58 | if (key == null || value == null) { 59 | continue; 60 | } 61 | map.put(key, value); 62 | } 63 | } 64 | return map.isEmpty() ? null : map; 65 | } 66 | 67 | private DocumentBuilder documentBuilder; 68 | 69 | 70 | @Override 71 | public Object marshal(final Map v) throws Exception { 72 | return null; 73 | } 74 | 75 | public SpreedlyNestedMapAdapter() { 76 | try { 77 | DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 78 | documentBuilder = dbf.newDocumentBuilder(); 79 | } catch(Exception e) { 80 | // TODO - Handle Exception 81 | } 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/internal/SpreedlyPaymentMethodCreateRequest.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model.internal; 2 | 3 | import javax.xml.bind.annotation.XmlElement; 4 | import javax.xml.bind.annotation.XmlRootElement; 5 | 6 | import cc.protea.spreedly.model.SpreedlyCreditCard; 7 | import javax.xml.bind.annotation.XmlRootElement; 8 | 9 | @XmlRootElement(name = "payment_method") 10 | public class SpreedlyPaymentMethodCreateRequest { 11 | 12 | @XmlElement(name = "credit_card") public SpreedlyCreditCard creditCard; 13 | @XmlElement(name = "email") public String email; 14 | @XmlElement(name = "data") public Object data; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/internal/SpreedlyPaymentMethodListResponse.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model.internal; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import javax.xml.bind.annotation.XmlElement; 7 | import javax.xml.bind.annotation.XmlRootElement; 8 | 9 | import cc.protea.spreedly.model.SpreedlyPaymentMethod; 10 | 11 | @XmlRootElement(name = "payment_methods") 12 | public class SpreedlyPaymentMethodListResponse { 13 | 14 | @XmlElement(name = "payment_method") 15 | public List paymentMethods = new ArrayList(); 16 | 17 | } -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/internal/SpreedlyPaymentMethodUpdate.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model.internal; 2 | 3 | import javax.xml.bind.annotation.XmlElement; 4 | import javax.xml.bind.annotation.XmlRootElement; 5 | 6 | @XmlRootElement(name = "gateway") 7 | public class SpreedlyPaymentMethodUpdate { 8 | 9 | @XmlElement(name = "remove_from_gateway") public String gatewayAccountToken; 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/cc/protea/spreedly/model/internal/SpreedlyTransactionListResponse.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model.internal; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import javax.xml.bind.annotation.XmlElement; 7 | import javax.xml.bind.annotation.XmlRootElement; 8 | 9 | import cc.protea.spreedly.model.SpreedlyTransactionResponse; 10 | 11 | @XmlRootElement(name = "transactions") 12 | public class SpreedlyTransactionListResponse { 13 | 14 | @XmlElement(name = "transaction") 15 | public List transactions = new ArrayList(); 16 | 17 | } -------------------------------------------------------------------------------- /src/test/java/cc/protea/spreedly/SpreedlyErrorHandlingTest.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly; 2 | 3 | import java.io.File; 4 | import java.io.FileNotFoundException; 5 | import java.net.URISyntaxException; 6 | import java.net.URL; 7 | import java.util.Scanner; 8 | 9 | import javax.xml.bind.JAXBContext; 10 | import javax.xml.bind.Unmarshaller; 11 | 12 | import org.junit.Assert; 13 | import org.junit.Before; 14 | import org.junit.Test; 15 | 16 | import cc.protea.spreedly.model.SpreedlyTransactionResponse; 17 | import cc.protea.spreedly.model.internal.SpreedlyErrors; 18 | import cc.protea.spreedly.model.internal.SpreedlyNestedMapAdapter; 19 | 20 | // Example taken from https://docs.spreedly.com/payment-gateways/paypal/ 21 | // 22 | // This tests most of the stranger XML parsing. 23 | public class SpreedlyErrorHandlingTest { 24 | 25 | SpreedlyNestedMapAdapter adapter; 26 | JAXBContext context; 27 | Unmarshaller unmarshaller; 28 | String xml; 29 | SpreedlyUtil spreedlyUtil; 30 | 31 | @Before 32 | public void before() throws URISyntaxException, FileNotFoundException { 33 | spreedlyUtil = new SpreedlyUtil(null, null); 34 | URL url = getClass().getResource("/SpreedlyTransactionResponseError.xml"); 35 | File file = new File(url.toURI()); 36 | xml = new Scanner(file).useDelimiter("\\Z").next(); 37 | } 38 | 39 | @Test 40 | public void testUnderlying() { 41 | SpreedlyErrors errors = spreedlyUtil.convert(xml, SpreedlyErrors.class, false); 42 | Assert.assertNotNull(errors); 43 | Assert.assertNotNull(errors.errors); 44 | Assert.assertEquals(2, errors.errors.size()); 45 | Assert.assertEquals(errors.errors.get(0).error, "Merchant id number can't be blank"); 46 | Assert.assertEquals(errors.errors.get(0).key, "errors.blank"); 47 | Assert.assertEquals(errors.errors.get(0).attribute, "merchant_id_number"); 48 | } 49 | 50 | @Test 51 | public void test() { 52 | try { 53 | spreedlyUtil.convert(xml, SpreedlyTransactionResponse.class); 54 | } catch (SpreedlyException e) { 55 | Assert.assertEquals("errors.blank", e.errorCode); 56 | Assert.assertEquals("Merchant id number can't be blank", e.errorMessage); 57 | } 58 | } 59 | 60 | @Test 61 | public void testAddError() { 62 | try { 63 | spreedlyUtil.convert(xml, SpreedlyTransactionResponse.class); 64 | } catch (SpreedlyException e) { 65 | SpreedlyTransactionResponse response = spreedlyUtil.addError(SpreedlyTransactionResponse.class, e); 66 | Assert.assertNotNull(response); 67 | Assert.assertEquals(false, response.succeeded); 68 | Assert.assertNotNull(response.message); 69 | Assert.assertEquals("Merchant id number can't be blank", response.message.message); 70 | Assert.assertEquals("errors.blank", response.message.key); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/test/java/cc/protea/spreedly/SpreedlyTest.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly; 2 | 3 | import java.util.List; 4 | 5 | import cc.protea.spreedly.model.SpreedlyGatewayAccount; 6 | import cc.protea.spreedly.model.SpreedlyGatewayAccountState; 7 | import cc.protea.spreedly.model.SpreedlyGatewayCredential; 8 | import org.junit.Assert; 9 | import org.junit.Before; 10 | import org.junit.Test; 11 | 12 | import cc.protea.spreedly.model.SpreedlyGatewayProvider; 13 | import cc.protea.spreedly.model.SpreedlyGatewayRedactResponse; 14 | 15 | 16 | public class SpreedlyTest { 17 | 18 | Spreedly spreedly; 19 | SpreedlyGatewayAccount testAccount; 20 | 21 | @Before 22 | public void before() { 23 | spreedly = SpreedlyTest.getSpreedly(); 24 | } 25 | 26 | @Test 27 | public void testGetGatewayProviders() throws Exception { 28 | if (spreedly == null) { 29 | return; 30 | } 31 | final List list = spreedly.listGatewayProviders(); 32 | Assert.assertNotNull(list); 33 | Assert.assertTrue(! list.isEmpty()); 34 | } 35 | 36 | @Test 37 | public void testCreate() throws Exception { 38 | if (spreedly == null) { 39 | return; 40 | } 41 | SpreedlyGatewayAccount account = new SpreedlyGatewayAccount(); 42 | account.gatewayType = "sage"; 43 | SpreedlyGatewayCredential c = new SpreedlyGatewayCredential(); 44 | c.name = "merchant_id_number"; 45 | c.value = "12345"; 46 | account.credentials.add(c); 47 | 48 | final SpreedlyGatewayAccount createdAccount = spreedly.create(account); 49 | Assert.assertNotNull(createdAccount); 50 | Assert.assertTrue(createdAccount.getToken() == "sage"); 51 | Assert.assertTrue(createdAccount.getGatewayType() == "sage"); 52 | Assert.assertTrue(!createdAccount.getCredentials().isEmpty()); 53 | Assert.assertTrue(createdAccount.getCredentials().get(0).getName() == "merchant_id_number"); 54 | Assert.assertTrue(createdAccount.getCredentials().get(0).getValue() == "12345"); 55 | 56 | testAccount = createdAccount; 57 | } 58 | 59 | @Test 60 | public void testRedact() throws Exception { 61 | if (spreedly == null) { 62 | return; 63 | } 64 | 65 | SpreedlyGatewayRedactResponse redactedAccount = spreedly.redact(testAccount); 66 | Assert.assertTrue(redactedAccount.getState() == SpreedlyGatewayAccountState.REDACTED); 67 | } 68 | 69 | @Test 70 | public void testRetain() throws Exception { 71 | if (spreedly == null) { 72 | return; 73 | } 74 | SpreedlyGatewayAccount retainedAccount = spreedly.retain(testAccount); 75 | Assert.assertTrue(retainedAccount.getState() == SpreedlyGatewayAccountState.RETAINED); 76 | } 77 | 78 | @Test 79 | public void testGetGatewayAccounts() throws Exception { 80 | if (spreedly == null) { 81 | return; 82 | } 83 | final List list = spreedly.listGatewayAccounts(); 84 | Assert.assertNotNull(list); 85 | Assert.assertTrue(! list.isEmpty()); 86 | } 87 | 88 | public static Spreedly getSpreedly() { 89 | final String environmentKey = SpreedlyTest.getEnvironmentKey(); 90 | final String apiSecret = SpreedlyTest.getApiSecret(); 91 | if (environmentKey == null || apiSecret == null) { 92 | return null; 93 | } 94 | return new Spreedly(environmentKey, apiSecret); 95 | } 96 | 97 | private static String getEnvironmentKey() { 98 | return System.getenv("SPREEDLYCORE_ENVIRONMENT_KEY"); 99 | } 100 | 101 | private static String getApiSecret() { 102 | return System.getenv("SPREEDLYCORE_API_SECRET"); 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /src/test/java/cc/protea/spreedly/model/internal/SpreedlyGatewayAccountUpdateTest.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model.internal; 2 | 3 | import cc.protea.spreedly.model.SpreedlyGatewayAccount; 4 | import cc.protea.spreedly.model.SpreedlyGatewayCredential; 5 | import junit.framework.Assert; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | 9 | import javax.xml.bind.JAXBContext; 10 | import javax.xml.bind.JAXBException; 11 | import javax.xml.bind.Marshaller; 12 | import javax.xml.bind.Unmarshaller; 13 | import java.io.File; 14 | import java.io.FileNotFoundException; 15 | import java.io.StringWriter; 16 | import java.net.URISyntaxException; 17 | import java.net.URL; 18 | import java.util.Scanner; 19 | 20 | public class SpreedlyGatewayAccountUpdateTest { 21 | 22 | JAXBContext context; 23 | Marshaller marshaller; 24 | Unmarshaller unmarshaller; 25 | String xml; 26 | 27 | @Before 28 | public void before() throws JAXBException, URISyntaxException, FileNotFoundException { 29 | 30 | context = JAXBContext.newInstance(SpreedlyGatewayAccountUpdate.class); 31 | marshaller = context.createMarshaller(); 32 | unmarshaller = context.createUnmarshaller(); 33 | 34 | URL url = getClass().getResource("/SpreedlyGatewayAccountUpdate.xml"); 35 | xml = new Scanner(new File(url.toURI())).useDelimiter("\\Z").next(); 36 | } 37 | 38 | @Test 39 | public void test() throws JAXBException { 40 | 41 | SpreedlyGatewayAccount account = new SpreedlyGatewayAccount(); 42 | account.gatewayType = "sage"; 43 | SpreedlyGatewayCredential c = new SpreedlyGatewayCredential(); 44 | c.name = "merchant_id_number"; 45 | c.value = "12345"; 46 | account.credentials.add(c); 47 | c = new SpreedlyGatewayCredential(); 48 | c.name = "merchant_key_number"; 49 | c.value = "24601"; 50 | account.credentials.add(c); 51 | 52 | SpreedlyGatewayAccountUpdate obj = new SpreedlyGatewayAccountUpdate(account); 53 | String response = get(obj); 54 | Assert.assertNotNull(response); 55 | Assert.assertEquals(xml, response); 56 | } 57 | 58 | String get(SpreedlyGatewayAccountUpdate object) throws JAXBException { 59 | StringWriter writer = new StringWriter(); 60 | marshaller.marshal(object, writer); 61 | return writer.toString(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/test/java/cc/protea/spreedly/model/internal/SpreedlyTransactionResponseTest.java: -------------------------------------------------------------------------------- 1 | package cc.protea.spreedly.model.internal; 2 | 3 | import java.io.File; 4 | import java.net.URISyntaxException; 5 | import java.net.URL; 6 | 7 | import javax.xml.bind.JAXBContext; 8 | import javax.xml.bind.JAXBException; 9 | import javax.xml.bind.Unmarshaller; 10 | 11 | import junit.framework.Assert; 12 | 13 | import org.junit.Before; 14 | import org.junit.Test; 15 | 16 | import cc.protea.spreedly.model.SpreedlyTransactionResponse; 17 | 18 | // Example taken from https://docs.spreedly.com/payment-gateways/paypal/ 19 | // 20 | // This tests most of the stranger XML parsing. 21 | 22 | public class SpreedlyTransactionResponseTest { 23 | 24 | SpreedlyNestedMapAdapter adapter; 25 | JAXBContext context; 26 | Unmarshaller unmarshaller; 27 | File xml; 28 | 29 | @Before 30 | public void before() throws JAXBException, URISyntaxException { 31 | context = JAXBContext.newInstance(SpreedlyTransactionResponse.class); 32 | unmarshaller = context.createUnmarshaller(); 33 | adapter = new SpreedlyNestedMapAdapter(); 34 | URL url = getClass().getResource("/SpreedlyTransactionResponse.xml"); 35 | xml = new File(url.toURI()); 36 | } 37 | 38 | @Test 39 | public void test() throws JAXBException { 40 | SpreedlyTransactionResponse response = (SpreedlyTransactionResponse) unmarshaller.unmarshal(xml); 41 | Assert.assertNotNull(response); 42 | Assert.assertEquals("1vcqQrU0d9f4NB5vdnx5wsoaAss", response.token); 43 | Assert.assertNotNull(response.gatewaySpecificResponseFields); 44 | Assert.assertFalse(response.gatewaySpecificResponseFields.isEmpty()); 45 | Assert.assertEquals("wax@example.com", response.gatewaySpecificResponseFields.get("payer")); 46 | Assert.assertEquals("messages.transaction_succeeded", response.message.key); 47 | Assert.assertEquals("Succeeded!", response.message.message); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/resources/SpreedlyGatewayAccountUpdate.xml: -------------------------------------------------------------------------------- 1 | sage1234524601 2 | -------------------------------------------------------------------------------- /src/test/resources/SpreedlyTransactionResponse.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 80 4 | true 5 | 2014-11-11T01:08:44Z 6 | 2014-11-11T01:08:44Z 7 | USD 8 | true 9 | succeeded 10 | 1vcqQrU0d9f4NB5vdnx5wsoaAss 11 | PurchaseViaReference 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | Y 21 | 22 | 23 | 24 | 25 | wax@example.com 26 | Waxillium 27 | Ladrian 28 | 3911 Main Street 29 | Apartment 3 30 | Wanaque 31 | NJ 32 | 28592-8851 33 | US 34 | 35 | 36 | 61 37 | Succeeded! 38 | 8XJtbE1p4NTZ6fFqwwn0GrkjEmW 39 | 40 | true 41 | Successful purchase 42 | 43 | 44 | 45 | 46 | false 47 | 48 | 49 | false 50 | 2014-11-11T01:08:44Z 51 | 2014-11-11T01:08:44Z 52 | 53 | KL7jgc4iy3MSMXfmqUNLVSHXmxN 54 | 55 | 56 | -------------------------------------------------------------------------------- /src/test/resources/SpreedlyTransactionResponseError.xml: -------------------------------------------------------------------------------- 1 | 2 | Merchant id number can't be blank 3 | Merchant key number can't be blank 4 | 5 | -------------------------------------------------------------------------------- /target/test-classes/SpreedlyTransactionResponse.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 80 4 | true 5 | 2014-11-11T01:08:44Z 6 | 2014-11-11T01:08:44Z 7 | USD 8 | true 9 | succeeded 10 | 1vcqQrU0d9f4NB5vdnx5wsoaAss 11 | PurchaseViaReference 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | Y 21 | 22 | 23 | 24 | 25 | wax@example.com 26 | Waxillium 27 | Ladrian 28 | 3911 Main Street 29 | Apartment 3 30 | Wanaque 31 | NJ 32 | 28592-8851 33 | US 34 | 35 | 36 | 61 37 | Succeeded! 38 | 8XJtbE1p4NTZ6fFqwwn0GrkjEmW 39 | 40 | true 41 | Successful purchase 42 | 43 | 44 | 45 | 46 | false 47 | 48 | 49 | false 50 | 2014-11-11T01:08:44Z 51 | 2014-11-11T01:08:44Z 52 | 53 | KL7jgc4iy3MSMXfmqUNLVSHXmxN 54 | 55 | 56 | --------------------------------------------------------------------------------