tixbit 0.2.1 → 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 CHANGED
@@ -95,7 +95,7 @@ tixbit link start <listing-id> --quantity 1 --email buyer@example.com --max-pric
95
95
  tixbit link complete <order-reference>
96
96
  ```
97
97
 
98
- The second command checks approval, sends one Stripe MPP credential, and reports whether the ticket was issued. If approval is still pending, it returns the same URL without sending payment. If the payment result is uncertain, use `link complete` with the same order reference. The CLI stores the purchase key in a private file under `~/.local/state/tixbit/link` (or `XDG_STATE_HOME`) and never prints or saves the Link payment token. Keep that file until the order is settled. Each command returns JSON; `approval_required` and payment failures use exit code 2.
98
+ The second command checks approval, sends one Stripe MPP credential, and reports whether the ticket was issued. If approval is still pending, it returns the same URL without sending payment. After payment submission, the CLI will not send that payment again. If the result is `pending`, do not start another checkout. Contact TixBit support with the order reference so the charge and ticket can be reconciled. The CLI stores the purchase key in a private file under `~/.local/state/tixbit/link` (or `XDG_STATE_HOME`) and never prints or saves the Link payment token. Keep that file until the order is settled. Each command returns JSON; `approval_required` and payment failures use exit code 2.
99
99
 
100
100
  Each spend request includes its TixBit order reference in the approval details. Link can still rate limit a matching amount and merchant for a short time, even after a request is canceled. If Link rejects a request, the CLI reports a safe error code such as `LINK_DUPLICATE_REQUEST` or `LINK_NETWORK_UNAVAILABLE` without printing Link credentials.
101
101
 
package/dist/cli.js CHANGED
@@ -428,6 +428,20 @@ var TixBitClient = class {
428
428
  const body = await response.json().catch(() => ({}));
429
429
  const orderReference = normalizeOrderReference(body.orderReference);
430
430
  const receiptUrl = normalizeReceiptUrl(body.receiptUrl);
431
+ if (response.status >= 500 && body.status !== "manual_review_required") {
432
+ return {
433
+ success: false,
434
+ status: "pending",
435
+ idempotencyKey,
436
+ orderReference,
437
+ receiptUrl,
438
+ error: {
439
+ code: "PURCHASE_OUTCOME_AMBIGUOUS",
440
+ message: "The server failed to confirm the purchase outcome."
441
+ },
442
+ action: "Check the order with the same idempotency key. Do not create a new payment or purchase attempt."
443
+ };
444
+ }
431
445
  if (response.status === 402) {
432
446
  const order = normalizePurchaseOrder(
433
447
  body.order,
@@ -1049,7 +1063,15 @@ async function startLinkPurchase(input) {
1049
1063
  }
1050
1064
  async function completeLinkPurchase(orderReference) {
1051
1065
  const state = await loadState(orderReference);
1052
- if (state.result?.status === "fulfilled" || state.result?.status === "manual_review_required") return state.result;
1066
+ if (state.result) return state.result;
1067
+ if (state.paymentAttempted) return {
1068
+ success: false,
1069
+ status: "pending",
1070
+ orderReference,
1071
+ amountCents: state.amountCents,
1072
+ error: { code: "PURCHASE_OUTCOME_AMBIGUOUS", message: "Payment may have been submitted, but the result is unknown." },
1073
+ action: "Do not retry payment or start another checkout. Contact TixBit support with this order reference."
1074
+ };
1053
1075
  const approval = await linkCli(["spend-request", "retrieve", state.spendRequestId, "--include", "shared_payment_token"]);
1054
1076
  if (["denied", "declined", "expired", "canceled", "cancelled"].includes(String(approval.status))) {
1055
1077
  return {
@@ -1097,6 +1119,8 @@ async function completeLinkPurchase(orderReference) {
1097
1119
  }
1098
1120
  });
1099
1121
  let decline = false;
1122
+ state.paymentAttempted = true;
1123
+ await saveState(state);
1100
1124
  const client2 = new TixBitClient({
1101
1125
  paymentEndpoint: paymentEndpoint(),
1102
1126
  timeoutMs: 9e4,
@@ -1123,13 +1147,11 @@ async function completeLinkPurchase(orderReference) {
1123
1147
  ...result.order && !decline ? { order: result.order } : {},
1124
1148
  ...!result.success ? {
1125
1149
  error: decline ? { code: "CARD_DECLINED", message: "Stripe declined the card selected in Link." } : result.error,
1126
- action: decline ? "Select another card in Link and start a new spend approval. No ticket was issued." : result.action
1150
+ action: decline ? "Select another card in Link and start a new spend approval. No ticket was issued." : result.status === "pending" ? "Payment may have succeeded. Do not retry or start another checkout. Contact TixBit support with this order reference." : result.action
1127
1151
  } : {}
1128
1152
  };
1129
- if (output2.status === "fulfilled" || output2.status === "manual_review_required") {
1130
- state.result = output2;
1131
- await saveState(state);
1132
- }
1153
+ state.result = output2;
1154
+ await saveState(state);
1133
1155
  return output2;
1134
1156
  }
1135
1157
 
package/dist/index.js CHANGED
@@ -408,6 +408,20 @@ var TixBitClient = class {
408
408
  const body = await response.json().catch(() => ({}));
409
409
  const orderReference = normalizeOrderReference(body.orderReference);
410
410
  const receiptUrl = normalizeReceiptUrl(body.receiptUrl);
411
+ if (response.status >= 500 && body.status !== "manual_review_required") {
412
+ return {
413
+ success: false,
414
+ status: "pending",
415
+ idempotencyKey,
416
+ orderReference,
417
+ receiptUrl,
418
+ error: {
419
+ code: "PURCHASE_OUTCOME_AMBIGUOUS",
420
+ message: "The server failed to confirm the purchase outcome."
421
+ },
422
+ action: "Check the order with the same idempotency key. Do not create a new payment or purchase attempt."
423
+ };
424
+ }
411
425
  if (response.status === 402) {
412
426
  const order = normalizePurchaseOrder(
413
427
  body.order,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tixbit",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Search events, browse listings, view seatmaps, and purchase TixBit tickets through MPP",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",