UNPKG

@chevre/domain

Version:

Chevre Domain Library for Node.js

764 lines (763 loc) 44.2 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.person2username = exports.onPaymentStatusChanged = void 0; exports.authorize = authorize; exports.findAcceptAction = findAcceptAction; exports.findAuthorizeAction = findAuthorizeAction; exports.findCheckAction = findCheckAction; exports.invalidatePaymentUrl = invalidatePaymentUrl; exports.voidPayTransaction = voidPayTransaction; exports.processVoidPayTransaction = processVoidPayTransaction; exports.publishPaymentUrl = publishPaymentUrl; const util = require("util"); const factory = require("../../factory"); // import type { TransactionProcessRepo } from '../../repo/transactionProcess'; const PayTransactionService = require("../assetTransaction/pay"); const publishOrderNumberIfNotExist_1 = require("../transaction/placeOrder/publishOrderNumberIfNotExist"); const factory_1 = require("./any/factory"); const fixOrderAsNeeded_1 = require("./any/fixOrderAsNeeded"); const handlePrePublishedPaymentMethodIdOnAuthorizing_1 = require("./any/handlePrePublishedPaymentMethodIdOnAuthorizing"); const onPaymentStatusChanged_1 = require("./any/onPaymentStatusChanged"); Object.defineProperty(exports, "onPaymentStatusChanged", { enumerable: true, get: function () { return onPaymentStatusChanged_1.onPaymentStatusChanged; } }); const person2username_1 = require("./any/person2username"); Object.defineProperty(exports, "person2username", { enumerable: true, get: function () { return person2username_1.person2username; } }); const verifyTicketTokenAsNeeded_1 = require("./any/verifyTicketTokenAsNeeded"); /** * 決済承認中止 * タスクから決済承認を取り消す */ function voidPayTransaction(params) { return (repos // settings: Settings ) => __awaiter(this, void 0, void 0, function* () { // 決済承認アクション確認不要(2024-03-12~) // 決済承認アクションを検索 // let authorizeActions = <factory.action.authorize.paymentMethod.any.IAction[]> // await repos.action.searchByPurpose({ // typeOf: factory.actionType.AuthorizeAction, // purpose: { // typeOf: params.purpose.typeOf, // id: params.purpose.id // } // }); // authorizeActions = authorizeActions.filter( // (a) => a.object.typeOf === factory.action.authorize.paymentMethod.any.ResultType.Payment // ); // // Chevreを使用した承認を取り消し // const authorizeActionsWithChevre = authorizeActions.filter((a) => { // return a.instrument?.identifier === factory.action.authorize.paymentMethod.any.ServiceIdentifier.Chevre; // }); // if (authorizeActionsWithChevre.length > 0) { // await processVoidPayTransaction(params)(repos); // } yield processVoidPayTransaction(params)(repos); // 決済URL無効化もここで処理 yield invalidatePaymentUrl(params)(repos); }); } function invalidatePaymentUrl(params) { // tslint:disable-next-line:max-func-body-length return (repos // settings: Settings ) => __awaiter(this, void 0, void 0, function* () { var _a, _b, _c, _d; if (params.purpose.typeOf !== factory.transactionType.PlaceOrder) { throw new factory.errors.Argument('purpose.typeOf', `must be ${factory.transactionType.PlaceOrder}`); } const transaction = yield repos.transaction.projectFieldsById({ typeOf: params.purpose.typeOf, id: params.purpose.id }, ['typeOf', 'status', 'object', 'project', 'seller', 'agent']); // const orderCancelled: boolean = params.purpose.result?.order?.orderStatus === factory.orderStatus.OrderCancelled; // if (transaction.status === factory.transactionStatusType.Confirmed) { // if (!orderCancelled) { // // no op // return; // } // } // support multiple accept actions(2025-02-25~) let acceptPayActions = yield repos.action.search({ project: { id: { $eq: transaction.project.id } }, typeOf: { $eq: factory.actionType.AcceptAction }, // actionStatus: { $in: [factory.actionStatusType.CompletedActionStatus] }, // all statuses(2025-02-26~) purpose: { id: { $in: [transaction.id] } }, object: { // transactionNumber: { $eq: paymentMethodIdByPaymentUrl }, typeOf: { $eq: factory.assetTransactionType.Pay } } }, ['object']); switch (transaction.status) { case factory.transactionStatusType.InProgress: throw new factory.errors.NotImplemented(`${transaction.status} not implemented`); case factory.transactionStatusType.Confirmed: // support OrderCanceled(2025-02-25~) const orderCancelled = ((_b = (_a = params.purpose.result) === null || _a === void 0 ? void 0 : _a.order) === null || _b === void 0 ? void 0 : _b.orderStatus) === factory.orderStatus.OrderCancelled; if (!orderCancelled) { const paymentMethodIdByPaymentUrl = (_c = transaction.object.paymentMethods) === null || _c === void 0 ? void 0 : _c.paymentMethodId; if (typeof paymentMethodIdByPaymentUrl === 'string') { acceptPayActions = acceptPayActions.filter(({ object }) => object.transactionNumber !== paymentMethodIdByPaymentUrl); } } break; default: // no op } const invalidatePaymentUrlTasks = []; const runsAt = new Date(); for (const acceptPayAction of acceptPayActions) { const paymentMethodIdByPaymentUrl = acceptPayAction.object.transactionNumber; const paymentMethodType = acceptPayAction.object.object.paymentMethod.identifier; if (typeof paymentMethodType === 'string' && paymentMethodType.length > 0) { // create task(2025-02-26~) // await PayTransactionService.invalidatePaymentUrl({})(repos, settings); const invalidatePaymentUrlData = { project: transaction.project, typeOf: factory.actionType.RefundAction, agent: { typeOf: transaction.seller.typeOf, name: (typeof transaction.seller.name === 'string') ? transaction.seller.name : String((_d = transaction.seller.name) === null || _d === void 0 ? void 0 : _d.ja), id: transaction.seller.id }, recipient: { typeOf: transaction.agent.typeOf, id: transaction.agent.id, name: transaction.agent.name }, object: [{ typeOf: factory.service.paymentService.PaymentServiceType.CreditCard, id: acceptPayAction.object.object.id, paymentMethod: { additionalProperty: [], name: paymentMethodType, typeOf: paymentMethodType, paymentMethodId: paymentMethodIdByPaymentUrl }, refundFee: 0 }], purpose: { typeOf: transaction.typeOf, id: transaction.id }, instrument: [] // ...(typeof params.sameAs?.id === 'string') ? { sameAs: params.sameAs } : undefined }; invalidatePaymentUrlTasks.push({ project: transaction.project, name: factory.taskName.InvalidatePaymentUrl, status: factory.taskStatus.Ready, runsAt, remainingNumberOfTries: 10, numberOfTried: 0, executionResults: [], data: invalidatePaymentUrlData }); } } if (invalidatePaymentUrlTasks.length > 0) { yield repos.task.saveMany(invalidatePaymentUrlTasks, { emitImmediately: true }); } // const paymentMethodIdByPaymentUrl = transaction.object.paymentMethods?.paymentMethodId; // if (typeof paymentMethodIdByPaymentUrl === 'string' && paymentMethodIdByPaymentUrl.length > 0) { // const acceptPayAction = (<Pick<IAcceptPayAction, 'object'>[]>await repos.action.search( // { // limit: 1, // page: 1, // project: { id: { $eq: transaction.project.id } }, // typeOf: { $eq: factory.actionType.AcceptAction }, // actionStatus: { $in: [factory.actionStatusType.CompletedActionStatus] }, // purpose: { id: { $in: [transaction.id] } }, // object: { // transactionNumber: { $eq: paymentMethodIdByPaymentUrl }, // typeOf: { $eq: factory.assetTransactionType.Pay } // } // }, // ['object'] // )).shift(); // if (acceptPayAction !== undefined) { // // const paymentMethodType = transaction.object.paymentMethods?.typeOf; // const paymentMethodType = acceptPayAction.object.object.paymentMethod.identifier; // if (typeof paymentMethodType === 'string' && paymentMethodType.length > 0) { // // chevreで決済URL無効化 // await PayTransactionService.invalidatePaymentUrl({ // project: transaction.project, // typeOf: factory.actionType.RefundAction, // agent: { // typeOf: transaction.seller.typeOf, // name: (typeof transaction.seller.name === 'string') // ? transaction.seller.name // : String(transaction.seller.name?.ja), // id: transaction.seller.id // }, // recipient: { // typeOf: transaction.agent.typeOf, // id: transaction.agent.id, // name: transaction.agent.name // }, // object: [{ // typeOf: factory.service.paymentService.PaymentServiceType.CreditCard, // id: acceptPayAction.object.object.id, // paymentMethod: { // additionalProperty: [], // name: paymentMethodType, // typeOf: paymentMethodType, // paymentMethodId: paymentMethodIdByPaymentUrl // }, // refundFee: 0 // }], // purpose: { typeOf: transaction.typeOf, id: transaction.id }, // instrument: [], // ...(typeof params.sameAs?.id === 'string') ? { sameAs: params.sameAs } : undefined // })(repos, settings); // } // } // } }); } /** * 決済承認中止 * apiもしくはタスクから決済承認を取り消す */ function processVoidPayTransaction(params) { // tslint:disable-next-line:max-func-body-length return (repos) => __awaiter(this, void 0, void 0, function* () { var _a, _b, _c, _d, _e; const cancelAction = Object.assign({ startTime: new Date(), agent: { id: params.project.id, typeOf: factory.organizationType.Project } }, (typeof ((_a = params.sameAs) === null || _a === void 0 ? void 0 : _a.id) === 'string') ? { sameAs: { id: params.sameAs.id, typeOf: 'Task' } } : undefined); let transaction; // アクションID指定の場合、進行中取引検証(2023-02-24~) if (typeof params.id === 'string') { transaction = (yield repos.transaction.projectFieldsInProgressById({ typeOf: params.purpose.typeOf, id: params.purpose.id }, ['typeOf', 'status'])); } else { transaction = (yield repos.transaction.projectFieldsById({ typeOf: params.purpose.typeOf, id: params.purpose.id }, ['typeOf', 'status', 'result'])); } // 承認アクションを取得 let authorizeActions; if (typeof params.id === 'string') { const authorizeAction = yield repos.action.findById({ typeOf: factory.actionType.AuthorizeAction, id: params.id }); // 取引内のアクションかどうか確認 if (authorizeAction.purpose.typeOf !== transaction.typeOf || authorizeAction.purpose.id !== transaction.id) { throw new factory.errors.Argument('Transaction', 'Action not found in the transaction'); } authorizeActions = [authorizeAction]; } else { authorizeActions = (yield repos.action.searchByPurpose({ typeOf: factory.actionType.AuthorizeAction, purpose: { typeOf: transaction.typeOf, id: transaction.id }, object: { typeOf: { $eq: factory.action.authorize.paymentMethod.any.ResultType.Payment } } })); switch (transaction.status) { case factory.transactionStatusType.InProgress: throw new factory.errors.NotImplemented(`${transaction.status} not implemented`); case factory.transactionStatusType.Confirmed: // OrderCancelledを考慮(2023-08-30~) const orderCancelled = ((_c = (_b = params.purpose.result) === null || _b === void 0 ? void 0 : _b.order) === null || _c === void 0 ? void 0 : _c.orderStatus) === factory.orderStatus.OrderCancelled; if (!orderCancelled) { // 取り消すべきアクションに絞る authorizeActions = authorizeActions.filter(({ actionStatus }) => actionStatus !== factory.actionStatusType.CompletedActionStatus); const actionIdsFromTransactionResult = (_e = (_d = transaction.result) === null || _d === void 0 ? void 0 : _d.authorizeActions) === null || _e === void 0 ? void 0 : _e.map(({ id }) => id); if (!Array.isArray(actionIdsFromTransactionResult)) { throw new factory.errors.Argument('Transaction', `${transaction.id} must have result.authorizeActions`); } authorizeActions = authorizeActions.filter(({ id }) => !actionIdsFromTransactionResult.includes(id)); // CreditCardIFでは、事前発行のpaymentMethodIdを承認時に指定するケースがある // その場合、paymentMethodIdの重複がありうる // exclude paymentMethodId in the order(2025-02-25~) let authorizedPaymentMethodIds = []; authorizedPaymentMethodIds = authorizeActions.filter(({ id }) => actionIdsFromTransactionResult.includes(id)) .map(({ object }) => object.paymentMethodId); authorizedPaymentMethodIds = [...new Set(authorizedPaymentMethodIds)]; authorizeActions = authorizeActions.filter(({ object }) => !authorizedPaymentMethodIds.includes(object.paymentMethodId)); } break; default: // no op } } const errors = []; for (const action of authorizeActions) { // 失敗するケースがあっても、残りが少なくとも処理されるようにエラーハンドリング try { yield repos.action.cancelWithVoid({ typeOf: action.typeOf, id: action.id, cancelAction }); // 取引が存在すれば中止 const transactionNumber = action.object.paymentMethodId; if (typeof transactionNumber === 'string' && transactionNumber.length > 0) { const payTransaction = (yield repos.assetTransaction.search({ limit: 1, page: 1, project: { id: { $eq: action.project.id } }, typeOf: factory.assetTransactionType.Pay, transactionNumber: { $eq: transactionNumber } }, ['_id', 'status'])).shift(); if (payTransaction !== undefined) { // ステータス検証(Expiredから実行される可能性がある) if (payTransaction.status !== factory.transactionStatusType.Canceled && payTransaction.status !== factory.transactionStatusType.Expired) { yield PayTransactionService.cancel({ transactionNumber })(repos); } } } } catch (error) { errors.push(error); } } if (errors.length > 0) { throw errors[0]; } }); } /** * 外部決済ロケーションを発行する */ function publishPaymentUrl(params) { return (repos, settings) => __awaiter(this, void 0, void 0, function* () { var _a; const { paymentServiceType, purpose, project } = params; if (purpose.typeOf !== factory.transactionType.PlaceOrder) { throw new factory.errors.NotImplemented(`purpose.typeOf '${purpose.typeOf} not implemented'`); } try { const transaction = yield repos.transaction.projectFieldsInProgressById({ typeOf: purpose.typeOf, id: purpose.id }, ['expires', 'seller', 'project']); // publishOrderNumber(2025-03-11~) yield (0, publishOrderNumberIfNotExist_1.publishOrderNumberIfNotExist)({ project: { id: transaction.project.id }, id: transaction.id, object: { orderDate: new Date() } })(repos); // 取引番号生成 let transactionNumber; // support ticketToken(2024-08-21~) const { permitOrInvoice } = yield (0, verifyTicketTokenAsNeeded_1.verifyTicketTokenAsNeeded)({ project, object: params.object, paymentServiceType, purpose })(repos); if ((permitOrInvoice === null || permitOrInvoice === void 0 ? void 0 : permitOrInvoice.typeOf) === factory.permit.PermitType.Permit) { const paymentMethodIdByPermit = permitOrInvoice === null || permitOrInvoice === void 0 ? void 0 : permitOrInvoice.identifier; if (typeof paymentMethodIdByPermit === 'string') { transactionNumber = paymentMethodIdByPermit; } } if (typeof transactionNumber !== 'string') { const publishTransactionNumberResult = yield repos.transactionNumber.publishByTimestamp({ startDate: new Date() }); transactionNumber = publishTransactionNumberResult.transactionNumber; } let result; // URL発行 const authorizeObject = Object.assign(Object.assign({}, params.object), { accountId: '', paymentMethodId: transactionNumber, typeOf: factory.action.authorize.paymentMethod.any.ResultType.Payment }); const startParams = (0, factory_1.creatPublishPaymentUrlParams)(Object.assign({ object: authorizeObject, paymentServiceType, transaction: transaction, transactionNumber: transactionNumber, location: params.location }, (typeof params.identifier === 'string') ? { identifier: params.identifier } : undefined)); const taskId = (_a = params.sameAs) === null || _a === void 0 ? void 0 : _a.id; result = yield PayTransactionService.publishPaymentUrl(startParams, { purposeAsTransaction: { id: transaction.id }, executor: (typeof taskId === 'string') ? { id: taskId } : {} // タスク関連付け(2024-05-22~) })(repos, settings); // 取引に保管 const paymentMethodByPaymentUrl = { // typeOf: params.object.paymentMethod, // discontinue(2024-06-05~) paymentMethodId: result.paymentMethodId // paymentUrl: result.paymentUrl, // migrate to recipe(2024-06-05~) // issuedThrough: { // id: (typeof startParams.object.id === 'string') ? startParams.object.id : '' // } // migrate to acceptAction(2024-06-05~) // GMO IFを保管(2024-01-01~) // entryTranArgs: result.entryTranArgs, // migrate to recipe(2024-06-05~) // entryTranResult: result.entryTranResult, // migrate to recipe(2024-06-05~) // execTranArgs: result.execTranArgs, // migrate to recipe(2024-06-05~) // execTranResult: result.execTranResult, // migrate to recipe(2024-06-05~) // paymentMethod: startParams.object.paymentMethod // 拡張(2024-01-04~) // migrate to acceptAction(2024-06-05~) }; yield repos.transaction.findByIdAndUpdateInProgress({ id: transaction.id, update: { $set: { 'object.paymentMethods': paymentMethodByPaymentUrl } } }); return { paymentMethodId: result.paymentMethodId, paymentUrl: result.paymentUrl }; } catch (error) { // 複数対応(2024-03-27~) if (Array.isArray(error)) { throw error[0]; } else { throw error; } } }); } /** * 承認アクションオブジェクトから冗長な属性を排除する */ function minimizeObjectIncludingPaymentMethodDetails(authorizeObjectIncludingPaymentMethodDetails) { const { accountId, paymentMethodId, typeOf } = authorizeObjectIncludingPaymentMethodDetails; return { authorizeObject: { accountId, paymentMethodId, typeOf } }; // optimize(2024-06-26~) } /** * 決済承認 */ function authorize(params) { // tslint:disable-next-line:cyclomatic-complexity max-func-body-length return (repos, settings) => __awaiter(this, void 0, void 0, function* () { var _a, _b; const { paymentServiceType, purpose, project } = params; if (purpose.typeOf !== factory.transactionType.PlaceOrder) { throw new factory.errors.NotImplemented(`purpose.typeOf '${purpose.typeOf} not implemented'`); } const transaction = yield repos.transaction.projectFieldsInProgressById({ typeOf: purpose.typeOf, id: purpose.id }, ['agent', 'expires', 'typeOf', 'project', 'seller']); const { confirmationNumber, orderNumber } = yield (0, fixOrderAsNeeded_1.fixOrderAsNeeded)({ project: { id: transaction.project.id }, purpose // paymentServiceType })(repos); // 取引番号生成 let transactionNumber; let pendingPaymentAgencyTransaction; let creditCard = params.object.creditCard; // ticketTokenを解釈(2024-08-13~) const { permitOrInvoice } = yield (0, verifyTicketTokenAsNeeded_1.verifyTicketTokenAsNeeded)({ project, object: params.object, paymentServiceType, purpose })(repos); /** * ticketTokenによって指定された決済方法ID */ let paymentMethodIdByTicketToken; if ((permitOrInvoice === null || permitOrInvoice === void 0 ? void 0 : permitOrInvoice.typeOf) === factory.permit.PermitType.Permit) { paymentMethodIdByTicketToken = permitOrInvoice === null || permitOrInvoice === void 0 ? void 0 : permitOrInvoice.identifier; if (typeof paymentMethodIdByTicketToken === 'string') { transactionNumber = paymentMethodIdByTicketToken; // メンバーシップ指定の場合、取引番号に適用(2024-08-13~) } } else if ((permitOrInvoice === null || permitOrInvoice === void 0 ? void 0 : permitOrInvoice.typeOf) === 'Invoice') { // support paymentServiceType.MovieTicket(2024-11-23~) if (typeof (permitOrInvoice === null || permitOrInvoice === void 0 ? void 0 : permitOrInvoice.paymentMethodId) === 'string') { paymentMethodIdByTicketToken = permitOrInvoice === null || permitOrInvoice === void 0 ? void 0 : permitOrInvoice.paymentMethodId; if (typeof paymentMethodIdByTicketToken === 'string') { transactionNumber = paymentMethodIdByTicketToken; } } } // リクエストでpaymentMethodIdを指定された場合、取引に保管されたpaymentMethodIdに一致すればそちらを適用(外部サイト決済対応) if (typeof params.object.paymentMethodId === 'string' && params.object.paymentMethodId.length > 0) { if (typeof paymentMethodIdByTicketToken === 'string') { if (paymentMethodIdByTicketToken !== params.object.paymentMethodId) { throw new factory.errors.Argument('ticketToken', 'not matched with paymentMethodId'); } } const { authorizeParams, existingCompletedAuthorizeAction } = yield (0, handlePrePublishedPaymentMethodIdOnAuthorizing_1.handlePrePublishedPaymentMethodIdOnAuthorizing)({ object: params.object, prePublishedPaymentMethodId: params.object.paymentMethodId, transaction })(repos); if (existingCompletedAuthorizeAction !== undefined) { return { id: existingCompletedAuthorizeAction.id }; } else if (authorizeParams !== undefined) { // creditCardを決済URL発行時の情報で上書き(2024-01-08~) // creditCard = authorizeParams.paymentMethodByTransaction.paymentMethod?.creditCard; creditCard = authorizeParams.creditCard; transactionNumber = params.object.paymentMethodId; pendingPaymentAgencyTransaction = authorizeParams.pendingPaymentAgencyTransaction; } else { throw new factory.errors.NotImplemented('pendingPaymentAgencyTransaction requied on paymentMethodId specified'); } } // 取引番号発行済でなければ発行 if (typeof transactionNumber !== 'string') { const publishTransactionNumberResult = yield repos.transactionNumber.publishByTimestamp({ startDate: new Date() }); transactionNumber = publishTransactionNumberResult.transactionNumber; } const movieTickets = (Array.isArray(params.object.movieTickets)) ? params.object.movieTickets.map(factory_1.createMovieTicket) : undefined; const { accountId } = yield fixAccountIdIfPossible({ object: params.object, project: { id: transaction.project.id } })(); const authorizeObjectIncludingPaymentMethodDetails = Object.assign(Object.assign(Object.assign(Object.assign({}, params.object), { accountId, paymentMethodId: transactionNumber, typeOf: factory.action.authorize.paymentMethod.any.ResultType.Payment }), (creditCard !== undefined) ? { creditCard } : undefined), (Array.isArray(movieTickets)) ? { movieTickets } : undefined); const { authorizeObject } = minimizeObjectIncludingPaymentMethodDetails(authorizeObjectIncludingPaymentMethodDetails); // 承認アクションを開始する const taskId = (_a = params.sameAs) === null || _a === void 0 ? void 0 : _a.id; const uniqueActionIdentifier = util.format(`%s:%s:%s`, factory.actionType.AuthorizeAction, factory.action.authorize.paymentMethod.any.ResultType.Payment, authorizeObject.paymentMethodId); const actionAttributes = Object.assign({ project: transaction.project, typeOf: factory.actionType.AuthorizeAction, object: authorizeObject, agent: { typeOf: transaction.agent.typeOf, id: transaction.agent.id }, instrument: { typeOf: factory.assetTransactionType.Pay, // 資産取引化(2024-03-11~) identifier: factory.action.authorize.paymentMethod.any.ServiceIdentifier.Chevre, transactionNumber }, recipient: { typeOf: transaction.seller.typeOf, id: transaction.seller.id, name: (typeof transaction.seller.name === 'string') ? transaction.seller.name : String((_b = transaction.seller.name) === null || _b === void 0 ? void 0 : _b.ja) }, purpose: { typeOf: transaction.typeOf, id: transaction.id }, identifier: uniqueActionIdentifier }, (typeof taskId === 'string') ? { sameAs: { id: taskId, typeOf: 'Task' } } : undefined // タスク関連付け(2024-04-22~) ); const action = yield repos.action.start(actionAttributes); let payTransaction; try { const startParams = (0, factory_1.creatPayTransactionStartParams)({ accountId, object: authorizeObjectIncludingPaymentMethodDetails, paymentServiceType, transaction: transaction, transactionNumber: transactionNumber, location: params.location, // confirmationNumber required(2025-02-12~) // orderNumber required(2025-02-14~) order: { confirmationNumber, orderNumber }, action: { id: action.id, typeOf: action.typeOf } }); payTransaction = yield PayTransactionService.start(startParams, Object.assign({ // useCheckByIdentifierIfNotYet: params.options.useCheckByIdentifierIfNotYet, executor: (typeof taskId === 'string') ? { id: taskId } : {}, purpose: { id: transaction.id }, checkedAction: params.options.checkedAction }, (pendingPaymentAgencyTransaction !== undefined) ? { pendingPaymentAgencyTransaction } : undefined))(repos, settings); } catch (error) { try { yield repos.action.giveUp({ typeOf: action.typeOf, id: action.id, error }); } catch (__) { // no op } // 即時に決済取引を中止するか?(2023-02-03~) if (params.options.useCancelPayTransactionOnFailed) { // abortエラーの場合は状態不明なので即時中止しない(2023-06-01~) // { // "type": "aborted", // "message": "The user aborted a request.", // "name": "AbortError" // } const rawError = Array.isArray(error) ? error[1] : undefined; if (rawError !== undefined && rawError.name !== 'AbortError') { yield processVoidPayTransaction({ project: actionAttributes.project, id: action.id, purpose: actionAttributes.purpose })(repos); } } // 複数対応(決済代行IFの場合、0:ChevreError,1:rawError)(2024-03-27~) if (Array.isArray(error)) { throw error[0]; } else { throw error; } } const result = (0, factory_1.createAuthorizeResult)(Object.assign({ payTransaction, object: authorizeObjectIncludingPaymentMethodDetails }, ((permitOrInvoice === null || permitOrInvoice === void 0 ? void 0 : permitOrInvoice.typeOf) === factory.permit.PermitType.Permit) ? { permit: permitOrInvoice } : undefined)); yield repos.action.completeWithVoid({ typeOf: action.typeOf, id: action.id, result: result }); return { id: action.id }; }); } /** * 承認しようとしているobjectからaccountIdを決定する */ function fixAccountIdIfPossible(params) { return ( // repos: { // action: ActionRepo; // authorization: AuthorizationRepo; // ticket: TicketRepo; // } // credentials: { // jwt: JWTCredentials; // } ) => __awaiter(this, void 0, void 0, function* () { var _a, _b; let accountId = ''; const fromLocation = (_a = params.object) === null || _a === void 0 ? void 0 : _a.fromLocation; const movieTickets = (_b = params.object) === null || _b === void 0 ? void 0 : _b.movieTickets; // discontinue token as fromLocation(ticketTokenへ移行するべき)(2024-12-18~) if (typeof fromLocation === 'string') { throw new factory.errors.NotImplemented('object.fromLocation as string not implemented'); // トークン化されたペイメントカード情報でリクエストされた場合、実ペイメントカード情報へ変換する // const { authorizedObject } = await verifyToken({ // project: { id: params.project.id }, // agent: { id: params.project.id, typeOf: factory.organizationType.Project }, // token: fromLocation // })(repos); // const paymentCardOwnershipInfo = authorizedObject; // if (Array.isArray(paymentCardOwnershipInfo)) { // throw new factory.errors.NotImplemented('fromLocation as an array not implemented'); // } // if (paymentCardOwnershipInfo.typeOf !== 'OwnershipInfo') { // throw new factory.errors.Argument('fromLocation', 'must be OwnershipInfo'); // } // if (paymentCardOwnershipInfo.typeOfGood.typeOf !== factory.permit.PermitType.Permit) { // throw new factory.errors.Argument('fromLocation', 'must be Permit'); // } // accountId = paymentCardOwnershipInfo.typeOfGood.identifier; } // 購入番号管理番号をaccountIdにセット(2024-03-24~) if (Array.isArray(movieTickets) && movieTickets.length > 0) { accountId = movieTickets[0].identifier; // 決済カードidentifierは1つのみ許可の前提 } return { accountId }; }); } function findAuthorizeAction(params) { return (repos) => __awaiter(this, void 0, void 0, function* () { var _a, _b; // タスク検索 const task = (yield repos.task.projectFields({ limit: 1, page: 1, id: { $eq: params.sameAs.id }, project: { id: { $eq: params.project.id } }, name: factory.taskName.AuthorizePayment }, ['status', 'executionResults'])).shift(); if (task === undefined) { throw new factory.errors.NotFound(factory.taskName.AuthorizePayment); } const errorByTask = (_a = task.executionResults.shift()) === null || _a === void 0 ? void 0 : _a.error; let defaultActionError; if (typeof errorByTask === 'string') { defaultActionError = { message: errorByTask }; } else if (typeof (errorByTask === null || errorByTask === void 0 ? void 0 : errorByTask.message) === 'string') { defaultActionError = { message: errorByTask.message, name: errorByTask.name }; } let action = Object.assign({ actionStatus: factory.actionStatusType.PotentialActionStatus }, (defaultActionError !== undefined) ? { error: defaultActionError } : undefined); switch (task.status) { case factory.taskStatus.Ready: break; default: // タスクがReadyでなければアクション検索 const authorizeAction = (yield repos.action.searchBySameAs({ sameAs: { id: { $eq: task.id } }, typeOf: { $eq: factory.actionType.AuthorizeAction } // purpose: { id: { $eq: String(params.purpose.id) } } })).shift(); if (authorizeAction !== undefined) { // purpose検証 if (((_b = authorizeAction.purpose) === null || _b === void 0 ? void 0 : _b.id) !== params.purpose.id) { throw new factory.errors.NotFound('Action'); } action = Object.assign({ id: authorizeAction.id, actionStatus: authorizeAction.actionStatus }, (authorizeAction.error !== undefined) ? { error: (Array.isArray(authorizeAction.error)) ? authorizeAction.error[0] : authorizeAction.error } : undefined); } } return action; }); } function findCheckAction(params) { return (repos) => __awaiter(this, void 0, void 0, function* () { var _a, _b; // タスク検索 const task = (yield repos.task.projectFields({ limit: 1, page: 1, id: { $eq: params.sameAs.id }, project: { id: { $eq: params.project.id } }, name: factory.taskName.CheckMovieTicket }, ['status', 'executionResults'])).shift(); if (task === undefined) { throw new factory.errors.NotFound(factory.taskName.CheckMovieTicket); } const errorByTask = (_a = task.executionResults.shift()) === null || _a === void 0 ? void 0 : _a.error; let defaultActionError; if (typeof errorByTask === 'string') { defaultActionError = { message: errorByTask }; } else if (typeof (errorByTask === null || errorByTask === void 0 ? void 0 : errorByTask.message) === 'string') { defaultActionError = { message: errorByTask.message, name: errorByTask.name }; } let action = Object.assign({ actionStatus: factory.actionStatusType.PotentialActionStatus }, (defaultActionError !== undefined) ? { error: defaultActionError } : undefined); switch (task.status) { case factory.taskStatus.Ready: break; default: // タスクがReadyでなければアクション検索 const authorizeAction = (yield repos.action.searchBySameAs({ sameAs: { id: { $eq: task.id } }, typeOf: { $eq: factory.actionType.CheckAction } // purpose: { id: { $eq: String(params.purpose.id) } } })).shift(); if (authorizeAction !== undefined) { // purpose検証 if (((_b = authorizeAction.purpose) === null || _b === void 0 ? void 0 : _b.id) !== params.purpose.id) { throw new factory.errors.NotFound('Action'); } // result from recipe(2024-06-10~) const purchaseNumberAuthResult = yield repos.action.findIMinimizedPurchaseNumberAuthResultByCheckMovieTicketRecipe({ project: { id: params.project.id }, recipeFor: { id: authorizeAction.id } }); action = Object.assign(Object.assign({ id: authorizeAction.id, actionStatus: authorizeAction.actionStatus }, (authorizeAction.error !== undefined) ? { error: (Array.isArray(authorizeAction.error)) ? authorizeAction.error[0] : authorizeAction.error } : undefined), (purchaseNumberAuthResult !== undefined) ? { result: { purchaseNumberAuthResult } } : undefined); } } return action; }); } function findAcceptAction(params) { return (repos) => __awaiter(this, void 0, void 0, function* () { var _a, _b; // タスク検索 const task = (yield repos.task.projectFields({ limit: 1, page: 1, id: { $eq: params.sameAs.id }, project: { id: { $eq: params.project.id } }, name: factory.taskName.PublishPaymentUrl }, ['status', 'executionResults'])).shift(); if (task === undefined) { throw new factory.errors.NotFound(factory.taskName.PublishPaymentUrl); } const errorByTask = (_a = task.executionResults.shift()) === null || _a === void 0 ? void 0 : _a.error; let defaultActionError; if (typeof errorByTask === 'string') { defaultActionError = { message: errorByTask }; } else if (typeof (errorByTask === null || errorByTask === void 0 ? void 0 : errorByTask.message) === 'string') { defaultActionError = { message: errorByTask.message, name: errorByTask.name }; } let action = Object.assign({ actionStatus: factory.actionStatusType.PotentialActionStatus }, (defaultActionError !== undefined) ? { error: defaultActionError } : undefined); switch (task.status) { case factory.taskStatus.Ready: break; default: // タスクがReadyでなければアクション検索 const acceptAction = (yield repos.action.searchBySameAs({ sameAs: { id: { $eq: task.id } }, typeOf: { $eq: factory.actionType.AcceptAction } // purpose: { id: { $eq: String(params.purpose.id) } } })).shift(); if (acceptAction !== undefined) { // purpose検証 if (((_b = acceptAction.purpose) === null || _b === void 0 ? void 0 : _b.id) !== params.purpose.id) { throw new factory.errors.NotFound('Action'); } const acceptActionWithResult = yield repos.action.findById({ id: acceptAction.id, typeOf: factory.actionType.AcceptAction }, ['result'], []); action = Object.assign(Object.assign({ id: acceptAction.id, actionStatus: acceptAction.actionStatus }, (acceptAction.error !== undefined) ? { error: (Array.isArray(acceptAction.error)) ? acceptAction.error[0] : acceptAction.error } : undefined), ((acceptActionWithResult === null || acceptActionWithResult === void 0 ? void 0 : acceptActionWithResult.result) !== undefined) ? { result: { paymentMethodId: acceptActionWithResult.result.paymentMethodId, paymentUrl: acceptActionWithResult.result.paymentUrl } } : undefined); } } return action; }); }