{"record":{"id":"7fe37ab6798f3e6f","repo":"GoogleCloudPlatform/microservices-demo","slug":"unacceptedcreditcard","errorCode":null,"errorMessage":"UnacceptedCreditCard","messagePattern":"UnacceptedCreditCard","errorType":"validation","errorClass":"UnacceptedCreditCard","httpStatus":null,"severity":"error","filePath":"src/paymentservice/charge.js","lineNumber":74,"sourceCode":" * Verifies the credit card number and (pretend) charges the card.\n *\n * @param {*} request\n * @return transaction_id - a random uuid.\n */\nmodule.exports = function charge (request) {\n  const { amount, credit_card: creditCard } = request;\n  const cardNumber = creditCard.credit_card_number;\n  const cardInfo = cardValidator(cardNumber);\n  const {\n    card_type: cardType,\n    valid\n  } = cardInfo.getCardDetails();\n\n  if (!valid) { throw new InvalidCreditCard(); }\n\n  // Only VISA and mastercard is accepted, other card types (AMEX, dinersclub) will\n  // throw UnacceptedCreditCard error.\n  if (!(cardType === 'visa' || cardType === 'mastercard')) { throw new UnacceptedCreditCard(cardType); }\n\n  // Also validate expiration is > today.\n  const currentMonth = new Date().getMonth() + 1;\n  const currentYear = new Date().getFullYear();\n  const { credit_card_expiration_year: year, credit_card_expiration_month: month } = creditCard;\n  if ((currentYear * 12 + currentMonth) > (year * 12 + month)) { throw new ExpiredCreditCard(cardNumber.replace('-', ''), month, year); }\n\n  logger.info(`Transaction processed: ${cardType} ending ${cardNumber.substr(-4)} \\\n    Amount: ${amount.currency_code}${amount.units}.${amount.nanos}`);\n\n  return { transaction_id: uuidv4() };\n};\n","sourceCodeStart":56,"sourceCodeEnd":87,"githubUrl":"https://github.com/GoogleCloudPlatform/microservices-demo/blob/72ba613a05f7fcee51cf1d0badff401b6ae7074d/src/paymentservice/charge.js#L56-L87","documentation":"UnacceptedCreditCard is thrown by charge() in src/paymentservice/charge.js when the card number is structurally valid but its detected type (from simple-card-validator) is not 'visa' or 'mastercard' — e.g. AMEX, Diners Club, Discover. The service deliberately accepts only VISA and MasterCard. It is a CreditCardError with code 400 (Invalid Argument) and the message includes the rejected card type.","triggerScenarios":"Passing a ChargeRequest whose credit_card_number is a valid but unsupported card: any AMEX number (starting 34/37), Diners Club (30/36/38), Discover (6011/65), JCB, etc.","commonSituations":"Users entering corporate AMEX cards at checkout; test suites reusing AMEX test numbers; integrating this demo service into an app that expects all major card networks to be supported.","solutions":["Use a VISA or MasterCard test number instead, e.g. '4012-8888-8888-1881' or '5555-5555-5555-4444'","If AMEX/other networks should be supported, edit charge.js to add the accepted card types to the check on line 74","Reject or reroute non-VISA/MasterCard cards in the frontend before calling Charge to give a friendlier error","Check card_type returned by simple-card-validator to confirm what type your number is being detected as"],"exampleFix":"// before\nif (!(cardType === 'visa' || cardType === 'mastercard')) { throw new UnacceptedCreditCard(cardType); }\n// after\nconst accepted = ['visa', 'mastercard', 'american_express'];\nif (!accepted.includes(cardType)) { throw new UnacceptedCreditCard(cardType); }","handlingStrategy":"validation","validationCode":"const cardValidator = require('simple-card-validator');\nfunction isAcceptedCard(cardNumber) {\n  const { card_type: cardType, valid } = cardValidator(cardNumber).getCardDetails();\n  return valid && (cardType === 'visa' || cardType === 'mastercard');\n}\nif (!isAcceptedCard(cardNumber)) {\n  return res.status(400).json({ error: 'Only VISA and MasterCard are accepted' });\n}","typeGuard":"function isAcceptedCardType(cardType) {\n  return cardType === 'visa' || cardType === 'mastercard';\n}","tryCatchPattern":"try {\n  const result = await paymentClient.Charge(chargeRequest);\n} catch (err) {\n  if (err.message === 'UnacceptedCreditCard' || /cannot process .* credit cards/i.test(err.message)) {\n    return res.status(400).json({ error: err.message, hint: 'Use a VISA or MasterCard.' });\n  }\n  throw err;\n}","preventionTips":["Filter card networks in the checkout UI to VISA/MasterCard only","Detect card type up front with simple-card-validator and show a friendly message before charging","Update test fixtures to avoid AMEX/Diners test numbers","If other networks are needed, extend the accepted list in charge.js before rollout"],"tags":["grpc","validation","payment","card-type"],"backgroundTag":"unsupported-card-type","analyzedSha":"72ba613a05f7fcee51cf1d0badff401b6ae7074d","analyzedAt":"2026-09-02T01:15:09.673Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}