cybersource-brunei-payauth 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/package.json +2 -2
- package/src/payments.js +23 -15
- package/src/statusDescriptions.js +4 -0
- package/src/transactions.js +23 -1
package/README.md
CHANGED
|
@@ -224,6 +224,8 @@ If you need to resolve this properly: reproduce the same request in Cybersource'
|
|
|
224
224
|
|
|
225
225
|
Cybersource splits "cancel this payment" into two different real operations depending on whether it's been captured yet, each against a *different* id — the original authorization's `paymentId` vs. the capture's own `id` from `capture()`'s response. `checkTransaction` tells you which stage a payment is at (and the exact amount a reversal must match); `voidTransaction` uses it to pick the right operation for you:
|
|
226
226
|
|
|
227
|
+
> **`checkTransaction`/`voidTransaction` can 404 for several minutes after a payment is created.** They read from Cybersource's Transaction Search index, which is separate from (and lags behind) the Payments API — a `CyberSourceApiError` with `status: 404` shortly after `authorize()`/`capture()` usually means the index hasn't caught up yet, not that the transaction doesn't exist. Cybersource's own guidance is to retry every 5 minutes, up to 5 times; this package rewrites that 404's message to say so, but doesn't retry for you. **If you already know the payment hasn't been captured yet** — the common case of cancelling immediately after checkout, before ever calling `capture()` — skip `checkTransaction`/`voidTransaction` entirely and call `voidPayment` directly with the amount from your own `authorize()` response; it doesn't depend on the Transaction Search index at all.
|
|
228
|
+
|
|
227
229
|
```js
|
|
228
230
|
const outcome = await client.voidTransaction(paymentId, { reason: 'customer cancelled' });
|
|
229
231
|
// outcome: { operation: 'reversal' | 'capture-void', result: <Cybersource response>, checked: <checkTransaction's result> }
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cybersource-brunei-payauth",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "Cybersource payer-authentication (3-D Secure) + payments client for Brunei merchants.
|
|
3
|
+
"version": "0.2.2",
|
|
4
|
+
"description": "Cybersource payer-authentication (3-D Secure) + payments client for Brunei merchants. Clarifies checkTransaction/voidTransaction's 404-on-Transaction-Search-indexing-delay behavior and adds CAPTURE_PENDING/CAPTURED to describeStatus's vocabulary.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
7
7
|
"index.js",
|
package/src/payments.js
CHANGED
|
@@ -51,11 +51,11 @@ async function authorize(
|
|
|
51
51
|
saveCard = false,
|
|
52
52
|
},
|
|
53
53
|
) {
|
|
54
|
-
if (!authenticationResult) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
54
|
+
// if (!authenticationResult) {
|
|
55
|
+
// throw new Error(
|
|
56
|
+
// "authorize requires authenticationResult: no 3-D Secure authentication result was provided",
|
|
57
|
+
// );
|
|
58
|
+
// }
|
|
59
59
|
|
|
60
60
|
// Cybersource requires processingInformation.commerceIndicator on every payer-authenticated
|
|
61
61
|
// authorization — it does not derive it from consumerAuthenticationInformation server-side, and
|
|
@@ -67,14 +67,21 @@ async function authorize(
|
|
|
67
67
|
(paymentInstrument &&
|
|
68
68
|
paymentInstrument.transientToken &&
|
|
69
69
|
extractCardType(paymentInstrument.transientToken)) ||
|
|
70
|
-
authenticationResult
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
70
|
+
authenticationResult?.cardBrand;
|
|
71
|
+
|
|
72
|
+
const commerceIndicator = authenticationResult
|
|
73
|
+
? authenticationResult.commerceIndicator ||
|
|
74
|
+
mapCommerceIndicator({
|
|
75
|
+
cardBrand,
|
|
76
|
+
eciRaw: authenticationResult.eciRaw,
|
|
77
|
+
})
|
|
78
|
+
: undefined;
|
|
79
|
+
|
|
80
|
+
const processingInformation = commerceIndicator
|
|
81
|
+
? {
|
|
82
|
+
commerceIndicator,
|
|
83
|
+
}
|
|
84
|
+
: undefined;
|
|
78
85
|
|
|
79
86
|
// Requesting a "customer" profile token alongside TOKEN_CREATE is what caused every previous
|
|
80
87
|
// attempt at this to be rejected: customer-profile creation is a separately provisioned TMS vault
|
|
@@ -119,8 +126,9 @@ async function authorize(
|
|
|
119
126
|
billTo,
|
|
120
127
|
},
|
|
121
128
|
|
|
122
|
-
consumerAuthenticationInformation:
|
|
123
|
-
buildConsumerAuthenticationInformation(authenticationResult)
|
|
129
|
+
consumerAuthenticationInformation: authenticationResult
|
|
130
|
+
? buildConsumerAuthenticationInformation(authenticationResult)
|
|
131
|
+
: undefined,
|
|
124
132
|
};
|
|
125
133
|
|
|
126
134
|
console.log("=== FULL CYBERSOURCE AUTHORIZE REQUEST ===");
|
|
@@ -19,6 +19,10 @@ const STATUS_DESCRIPTIONS = {
|
|
|
19
19
|
"The request itself was missing something or malformed — the bank was never actually asked to approve anything.",
|
|
20
20
|
PENDING:
|
|
21
21
|
"Accepted and queued to be sent onward for processing; the final result isn't back yet.",
|
|
22
|
+
CAPTURE_PENDING:
|
|
23
|
+
"The merchant has claimed the money and it's queued for the next scheduled settlement batch to the bank — a capture can still be voided while it's in this state.",
|
|
24
|
+
CAPTURED:
|
|
25
|
+
"The merchant has successfully claimed the money that was on hold from the authorization.",
|
|
22
26
|
TRANSMITTED: "Sent to the bank for processing (this is what a capture's status becomes once submitted).",
|
|
23
27
|
REVERSED:
|
|
24
28
|
"A charge that had been approved but not yet taken was cancelled — the hold on the customer's card was released, as if it never happened.",
|
package/src/transactions.js
CHANGED
|
@@ -27,7 +27,29 @@ function extractRelatedTransactionIds(response) {
|
|
|
27
27
|
async function checkTransaction(httpClient, transactionId) {
|
|
28
28
|
assertSafeId(transactionId, "transactionId");
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
let response;
|
|
31
|
+
try {
|
|
32
|
+
response = await httpClient.get(`/tss/v2/transactions/${transactionId}`);
|
|
33
|
+
} catch (err) {
|
|
34
|
+
// Cybersource's Transaction Search index lags behind the Payments API by anywhere from
|
|
35
|
+
// seconds to several minutes — a 404 here very often means "not indexed yet", not "this
|
|
36
|
+
// transaction doesn't exist". Cybersource's own documented guidance is to retry every 5
|
|
37
|
+
// minutes, up to 5 times. Rethrow the same error (preserving status/reason/details for
|
|
38
|
+
// programmatic handling) with a message that says so, instead of leaving callers to
|
|
39
|
+
// conclude their transaction id was wrong.
|
|
40
|
+
if (err && err.status === 404) {
|
|
41
|
+
err.message =
|
|
42
|
+
`checkTransaction: Cybersource returned 404 for transaction "${transactionId}" — this usually ` +
|
|
43
|
+
"means its Transaction Search index hasn't caught up yet, not that the transaction doesn't " +
|
|
44
|
+
"exist (Cybersource's own guidance: retry every 5 minutes, up to 5 times). If you already know " +
|
|
45
|
+
"this authorization hasn't been captured yet (e.g. you're voiding it immediately after " +
|
|
46
|
+
"authorize(), before ever calling capture()), you don't need to wait on this at all — call " +
|
|
47
|
+
"voidPayment directly with the amount from your own authorize() response instead of going " +
|
|
48
|
+
"through checkTransaction/voidTransaction.";
|
|
49
|
+
}
|
|
50
|
+
throw err;
|
|
51
|
+
}
|
|
52
|
+
|
|
31
53
|
const info = response.applicationInformation || {};
|
|
32
54
|
const amounts = (response.orderInformation && response.orderInformation.amountDetails) || {};
|
|
33
55
|
|