@chevre/domain
Version:
Chevre Domain Library for Node.js
764 lines (763 loc) • 44.2 kB
JavaScript
"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;
});
}