@mathrunet/masamune
Version:
Manages packages for the server portion (NodeJS) of the Masamune framework.
816 lines • 80.7 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
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 });
const functions = __importStar(require("firebase-functions/v2"));
const stripe = __importStar(require("stripe"));
const admin = __importStar(require("firebase-admin"));
const sendgrid = __importStar(require("../lib/functions/send_grid"));
const gmail = __importStar(require("../lib/functions/gmail"));
require("../lib/exntensions/string.extension");
const firebase_loader_1 = require("../lib/src/firebase_loader");
/**
* Performs various Stripe processes.
* Firestore integration is a must; please make Firestore available as well.
*
* Stripeの各種処理を実行します。
* Firestoreとの連携が必須です。Firestoreも利用可能にしてください。
*
* @param {string} process.env.PURCHASE_STRIPE_SECRETKEY
* API key (secret key) to connect to Stripe.
* Log in to the following URL and create a project.
* After the project is created, the secret key can be copied.
*
* Stripeへ接続するためのAPIキー(シークレットキー)。
* 下記URLにログインし、プロジェクトを作成します。
* プロジェクト作成後、シークレットキーをコピーすることができます。
*
* Production environment
* https://dashboard.stripe.com/apikeys
* Development enveironment
* https://dashboard.stripe.com/test/apikeys
*
* @param {string} process.env.PURCHASE_STRIPE_USERPATH
* Stripe user (customer) pass.
* Stripeのユーザー(カスタマー)用パス。
*
* @param {string} process.env.PURCHASE_STRIPE_PAYMENTPATH
* Path for payment method information to be placed under [process.env.PURCHASE_STRIPE_USERPATH].
* [process.env.PURCHASE_STRIPE_USERPATH]の下に配置する支払い方法の情報用パス。
*
* @param {string} process.env.PURCHASE_STRIPE_PURCHASEPATH
* Path for purchase information to be placed under [process.env.PURCHASE_STRIPE_USERPATH].
* [process.env.PURCHASE_STRIPE_USERPATH]の下に配置する購入情報用パス。
*
* @param {string} process.env.PURCHASE_STRIPE_EMAILPROVIDER
* Mail provider when sending mail. (gmail | sendgrid)
* メールを送信する際のメールプロバイダー。(gmail | sendgrid)
*
* @param {string} mode
* [required]
* Specifies the mode in which Stripe will run.
* Stripeの実行するモードを指定します。
*
* - create_account
* - Create a link to register to create a Stripe account to receive payments. Once these registrations are complete, an account will be created. The actual account information is stored in Firestore. Please refer there. 支払いを受け取るためのStripeアカウントを作成するための登録用リンクを作成します。これらの登録が完了するとアカウントが作成されます。実際のアカウント情報はFirestoreに保存されます。そちらを参照してください。
* - delete_account
* - Delete an account to receive payments already created. すでに作成された支払いを受け取るためのアカウントを削除します。
* - get_account
* - Get an account to receive payments already created. すでに作成された支払いを受け取るためのアカウントを取得します。
* - dashboard_account
* - Returns the URL of the dashboard for modifying information on an already created account to receive payments. Receipt of payments, etc. is also done from here. すでに作成された支払いを受け取るためのアカウントの情報を変更するためのダッシュボードのURLを返します。支払いの受け取りなどもここから行います。
*
* - create_customer_and_payment
* - Create a buyer (customer) for Stripe and a payment method associated with it. After creating this, use [create_purchase] to create the actual payment. The actual customer and payment information is stored in Firestore. Please refer there. Stripe用の購入者(カスタマー)とそれに紐づいた支払い方法を作成します。これを作成後、[create_purchase]で実際の支払いを作成します。 実際のカスタマーや支払い情報はFirestoreに保存されます。そちらを参照してください。
* - set_customer_default_payment
* - Set the default payment method for the buyer (customer) created by Stripe. Stripeで作成した購入者(カスタマー)に対してデフォルトの支払い方法を設定します。
* - delete_payment
* - Delete a payment method already created. すでに作成された支払い方法を削除します。
* - delete_customer
* - Delete a buyer (customer) already created. すでに作成された購入者(カスタマー)を削除します。
*
* - authorization
* - Before making a payment, the system performs a verification (authorization) to see if the card payment can be made. If payment is possible, [authorizedId] will be returned. If this is returned, complete the authorization with [confirm_authorization]. If it is not returned, payment cannot be made. 支払いを行う前にカード支払が可能かどうかを検証(オーソリ)を行います。支払いが可能な場合、[authorizedId]が返却されます。これが返却された場合[confirm_authorization]でオーソリを完了してください。返却されなかった場合、支払いはできません。
* - confirm_authorization
* - Complete the authorization using the [authorizedId] returned by [authorization]. [authorization]で返却された[authorizedId]を利用してオーソリを完了します。
*
* - create_purchase
* - Create a payment. After this, use [authorization_purchase] to authenticate 3D Secure, [confirm_purchase] to confirm the payment, and [capture_purchase] to make the actual payment. 決済を作成します。この跡に[authorization_purchase]で3Dセキュアの認証を行い、[confirm_purchase]で決済の確定、[capture_purchase]で実際の支払いを行います。
* - confirm_purchase
* - This is used to finalize the payment after the verification in the application is completed. This execution is mandatory. アプリ内の検証が完了したのち決済を確定させるために利用します。こちらの実行は必須です。
* - capture_purchase
* - After the settlement is confirmed by [confirm_purchase], the actual payment process is executed. Once this is completed, the actual transfer of money occurs. [confirm_purchase]で決済確定後、実際に支払いを行う処理を実行します。これが完了した時点で実際の金銭の移動が発生します。
* - refresh_purchase
* - Update payment method. 支払い方法を更新します。
* - cancel_purchase
* - Cancel the payment. After executing [capture_purchase], please execute [refund_purchase] as it will be a refund process. 支払いをキャンセルします。[capture_purchase]実行後は返金処理となるので[refund_purchase]を実行してください。
* - refund_purchase
* - Process refunds of applicable payments. 該当する支払いの返金処理を行います。
*
* - create_subscription
* - Subscribe to a new subscription. See Firestore for subscribed subscription data. 新しくサブスクリプションを購読します。 購読されたサブスクリプションのデータはFirestoreを参照してください。
* - delete_subscription
* - Cancel and delete subscribed subscriptions. 購読済みのサブスクリプションをキャンセルして削除します。
*
* @param {double} amount
* [required]
* Enter the amount with a decimal point.
* 金額を小数点付きで入力します。
*
* @param {int} count
* [required]
* Enter the number of pieces.
* 個数を入力します。
*
* @param {string} userId
* [required]
* Specify the purchaser's user ID.
* 購入者のユーザーIDを指定します。
*
* @param {string} orderId
* [required]
* Specify the order ID. This will be the database key.
* 注文IDを指定します。これがデータベースのキーとなります。
*
* @param {string} productId
* [required]
* Specify the product ID.
* 商品IDを指定します。
*
* @param {string} currency
* [optional]
* Enter the currency code (USD, JPY, etc.). If you do not enter a currency code, it will be set to JPY.
* 通貨コードを入力します(USD、JPYなど)。入力しない場合はJPYとなります。
*
* @param {string} online
* [optional]
* You can select whether the card's 3D Secure authentication should be online (whether the user supports the browser itself) or offline (whether the user supports it by sending an email, etc.)." If set to "true", the card is online.
* カードの3Dセキュア認証をオンライン(ユーザー自体がブラウザ対応するか)、オフライン(メール送信などで対応するか)を選択できます。"true"に設定されている場合はオンラインです。
*
* @param {double} revenueRatio
* [optional]
* Enter the rate of return for the operation. If not entered, it will be 0.
* 運営の収益率を入力します。入力しない場合は0となります。
*
* @param {string} targetUserId
* [optional]
* If a seller exists, specify its user ID. If not specified, the management will be the seller.
* 販売者が存在する場合そのユーザーIDを指定します。指定しない場合は運営が販売者となります。
*
* @param {string} description
* [optional]
* Enter a description of the product.
* 商品の説明を入力します。
*
* @param {string} emailFrom
* [optional]
* If using a credit card that supports 3D Secure, specify the source e-mail address to which the authentication e-mail will be sent. The destination email address will be set to the registered Stripe account.
* 3Dセキュア対応のクレジットカードを用いた場合、その認証用のメールを送信する際の送信元メールアドレスを指定します。送信先メールアドレスは登録されているStripeのアカウントが設定されます。
*
* @param {string} emailTitle
* [optional]
* Specify the title of the email to be sent for authentication when using a credit card that supports 3D Secure.
* 3Dセキュア対応のクレジットカードを用いた場合、その認証用のメールを送信する際のメールタイトルを指定します。
*
* @param {string} emailContent
* [optional]
* Specify the body of the e-mail to be sent for authentication when using a credit card that supports 3D Secure.
* 3Dセキュア対応のクレジットカードを用いた場合、その認証用のメールを送信する際のメール本文を指定します。{url}をリンククリック用URLに変換します。
*
* @param {string} locale
* [optional]
* Specify the purchaser's locale. Please specify like ja_JP.
* 購入者のロケールを指定します。ja_JPのように指定してください。
*
* @param {string} successUrl
* [required]
* Specify the URL to redirect to upon success due to browser settings, etc.
* ブラウザの設定等による成功時のリダイレクト先URLを指定します。
*
* @param {string} failureUrl
* [required]
* Specify the URL to redirect to upon failure due to browser settings, etc.
* ブラウザの設定等による失敗時のリダイレクト先URLを指定します。
*
* @param {string} returnUrl
* [required]
* Specify the URL to redirect to after authentication.
* 認証後のリダイレクト先URLを指定します。
*/
module.exports = (regions, options, data) => {
var _a, _b, _c, _d;
return functions.https.onCall({
region: (_a = options.region) !== null && _a !== void 0 ? _a : regions,
timeoutSeconds: options.timeoutSeconds,
memory: options.memory,
minInstances: options.minInstances,
concurrency: options.concurrency,
maxInstances: options.maxInstances,
serviceAccount: (_b = options === null || options === void 0 ? void 0 : options.serviceAccount) !== null && _b !== void 0 ? _b : undefined,
enforceAppCheck: (_c = options.enforceAppCheck) !== null && _c !== void 0 ? _c : undefined,
consumeAppCheckToken: (_d = options.consumeAppCheckToken) !== null && _d !== void 0 ? _d : undefined,
}, (query) => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32;
try {
let error = null;
const firestoreDatabaseIds = (_a = options.firestoreDatabaseIds) !== null && _a !== void 0 ? _a : [""];
for (const databaseId of firestoreDatabaseIds) {
try {
const apiKey = (_b = process.env.PURCHASE_STRIPE_SECRETKEY) !== null && _b !== void 0 ? _b : "";
const stripeUserPath = (_c = process.env.PURCHASE_STRIPE_USERPATH) !== null && _c !== void 0 ? _c : "plugins/stripe/user";
const stripePurchasePath = (_d = process.env.PURCHASE_STRIPE_PURCHASEPATH) !== null && _d !== void 0 ? _d : "purchase";
const stripePaymentPath = (_e = process.env.PURCHASE_STRIPE_PAYMENTPATH) !== null && _e !== void 0 ? _e : "payment";
const stripeEmailProvider = (_f = process.env.PURCHASE_STRIPE_EMAILPROVIDER) !== null && _f !== void 0 ? _f : "gmail";
const firestoreInstance = (0, firebase_loader_1.firestoreLoader)(databaseId);
const stripeClient = new stripe.Stripe(apiKey, {
apiVersion: "2025-01-27.acacia",
});
switch (query.data.mode) {
case "create_account": {
const userId = query.data.userId;
const locale = query.data.locale;
const refreshUrl = query.data.refreshUrl;
const returnUrl = query.data.returnUrl;
if (!locale) {
throw new functions.https.HttpsError("invalid-argument", "The locale is empty.");
}
if (!userId) {
throw new functions.https.HttpsError("invalid-argument", "The user id is empty.");
}
const country = locale.split("_")[1];
const doc = yield firestoreInstance.doc(`${stripeUserPath}/${userId}`).get();
const data = doc.data();
if (!data || !data["account"]) {
const account = yield stripeClient.accounts.create({
type: "express",
country: country !== null && country !== void 0 ? country : "JP",
});
const update = {};
update["@uid"] = userId;
update["@time"] = new Date();
update["user"] = userId;
update["account"] = account.id;
yield firestoreInstance.doc(`${stripeUserPath}/${userId}`).set(update, {
merge: true,
});
const endpoint = yield stripeClient.accountLinks.create({
type: "account_onboarding",
account: account.id,
refresh_url: refreshUrl,
return_url: returnUrl,
});
return {
next: "registration",
endpoint: endpoint.url,
accountId: account.id,
};
}
else {
if (data["capability"] && data["capability"]["transfers"]) {
return {
next: "none",
};
}
const res = yield stripeClient.accounts.retrieve(data["account"]);
if (res["capabilities"] && res["capabilities"]["transfers"] === "active") {
const update = {};
update["capability"] = {
transfers: true,
};
yield doc.ref.set(update, {
merge: true,
});
return {
next: "none",
};
}
else {
const endpoint = yield stripeClient.accountLinks.create({
type: "account_onboarding",
account: data["account"],
refresh_url: refreshUrl,
return_url: returnUrl,
});
return {
next: "registration",
endpoint: endpoint.url,
accountId: data["account"],
};
}
}
}
case "delete_account": {
const userId = query.data.userId;
if (!userId) {
throw new functions.https.HttpsError("invalid-argument", "The user id is empty.");
}
const doc = yield firestoreInstance.doc(`${stripeUserPath}/${userId}`).get();
const data = doc.data();
if (!data || !data["account"]) {
throw new functions.https.HttpsError("not-found", "Account id is not found.");
}
yield stripeClient.accounts.del(data["account"]);
const update = {};
update["account"] = admin.firestore.FieldValue.delete();
update["capability"] = admin.firestore.FieldValue.arrayRemove({
"transfers": true
});
yield doc.ref.set(update, {
merge: true,
});
return {
success: true,
};
}
case "get_account": {
const userId = query.data.userId;
if (!userId) {
throw new functions.https.HttpsError("invalid-argument", "The user id is empty.");
}
const doc = yield firestoreInstance.doc(`${stripeUserPath}/${userId}`).get();
const data = doc.data();
if (!data || !data["account"]) {
throw new functions.https.HttpsError("not-found", "Account id is not found.");
}
const res = yield stripeClient.accounts.retrieve(data["account"]);
return res;
}
case "dashboard_account": {
const userId = query.data.userId;
if (!userId) {
throw new functions.https.HttpsError("invalid-argument", "The user id is empty.");
}
const doc = yield firestoreInstance.doc(`${stripeUserPath}/${userId}`).get();
const data = doc.data();
if (!data || !data["account"]) {
throw new functions.https.HttpsError("not-found", "Account id is not found.");
}
const res = yield stripeClient.accounts.createLoginLink(data["account"]);
return {
endpoint: res["url"],
};
}
case "create_customer_and_payment": {
const userId = query.data.userId;
const successUrl = query.data.successUrl;
const cancelUrl = query.data.cancelUrl;
const authInstance = admin.auth();
if (!userId) {
throw new functions.https.HttpsError("invalid-argument", "The user id is empty.");
}
const user = yield authInstance.getUser(userId);
if (!user) {
throw new functions.https.HttpsError("not-found", "The user is not found.");
}
const doc = yield firestoreInstance.doc(`${stripeUserPath}/${userId}`).get();
const data = doc.data();
if (!data || !data["customer"]) {
const customer = yield stripeClient.customers.create({
metadata: {
"user_id": userId,
},
email: (_g = user.email) !== null && _g !== void 0 ? _g : (!data ? null : data["email"]),
});
const update = {};
update["@uid"] = userId;
update["@time"] = new Date();
update["user"] = userId;
update["customer"] = customer.id;
yield firestoreInstance.doc(`${stripeUserPath}/${userId}`).set(update, {
merge: true,
});
const session = yield stripeClient.checkout.sessions.create({
payment_method_types: ["card"],
mode: "setup",
customer: customer.id,
success_url: successUrl,
cancel_url: cancelUrl,
metadata: {
"user_id": userId,
},
});
return {
endpoint: session.url,
customerId: customer.id,
};
}
else {
const session = yield stripeClient.checkout.sessions.create({
payment_method_types: ["card"],
mode: "setup",
customer: data["customer"],
success_url: successUrl,
cancel_url: cancelUrl,
});
return {
endpoint: session.url,
customerId: data["customer"],
};
}
}
case "set_customer_default_payment": {
const userId = query.data.userId;
const paymentId = query.data.paymentId;
if (!paymentId) {
throw new functions.https.HttpsError("invalid-argument", "The payment id is empty.");
}
if (!userId) {
throw new functions.https.HttpsError("invalid-argument", "The user id is empty.");
}
const doc = yield firestoreInstance.doc(`${stripeUserPath}/${userId}`).get();
const data = doc.data();
if (!data || !data["customer"]) {
throw new functions.https.HttpsError("not-found", "The customer is empty.");
}
const payment = yield firestoreInstance.doc(`${stripeUserPath}/${userId}/${stripePaymentPath}/${paymentId}`).get();
const paymentData = payment.data();
if (!paymentData || !paymentData["id"]) {
throw new functions.https.HttpsError("not-found", "The payment method is empty.");
}
yield stripeClient.customers.update(data["customer"], {
invoice_settings: {
default_payment_method: paymentData["id"],
},
});
if (data["defaultPayment"] !== paymentData["id"]) {
const update = {};
update["defaultPayment"] = paymentData["id"];
yield doc.ref.set(update, {
merge: true,
});
}
return {
success: true,
};
}
case "delete_payment": {
const userId = query.data.userId;
const paymentId = query.data.paymentId;
if (!paymentId) {
throw new functions.https.HttpsError("invalid-argument", "The payment id is empty.");
}
if (!userId) {
throw new functions.https.HttpsError("invalid-argument", "The user id is empty.");
}
const doc = yield firestoreInstance.doc(`${stripeUserPath}/${userId}`).get();
const data = doc.data();
if (!data || !data["customer"]) {
throw new functions.https.HttpsError("not-found", "The customer is empty.");
}
const payment = yield firestoreInstance.doc(`${stripeUserPath}/${userId}/${stripePaymentPath}/${paymentId}`).get();
const paymentData = payment.data();
if (!paymentData || !paymentData["id"]) {
throw new functions.https.HttpsError("not-found", "The payment method is empty.");
}
yield stripeClient.paymentMethods.detach(paymentData["id"]);
if (data["defaultPayment"] === paymentData["id"]) {
const update = {};
update["defaultPayment"] = admin.firestore.FieldValue.delete();
yield doc.ref.set(update, {
merge: true,
});
}
return {
success: true,
};
}
case "delete_customer": {
const userId = query.data.userId;
if (!userId) {
throw new functions.https.HttpsError("invalid-argument", "The user id is empty.");
}
const doc = yield firestoreInstance.doc(`${stripeUserPath}/${userId}`).get();
const data = doc.data();
if (!data || !data["customer"]) {
throw new functions.https.HttpsError("not-found", "Customer id is not found.");
}
yield stripeClient.customers.del(data["customer"]);
const update = {};
update["customer"] = admin.firestore.FieldValue.delete();
yield doc.ref.set(update, {
merge: true,
});
return {
success: true,
};
}
case "authorization": {
const authInstance = admin.auth();
const amount = parseFloat(query.data.amount);
const currency = (_h = query.data.currency) !== null && _h !== void 0 ? _h : "jpy";
const returnUrl = query.data.returnUrl;
const online = query.data.online == "true";
const emailFrom = query.data.from;
const emailTitle = query.data.title;
const emailContent = query.data.content;
const userId = query.data.userId;
if (!userId) {
throw new functions.https.HttpsError("invalid-argument", "The user id is empty.");
}
const userDoc = yield firestoreInstance.doc(`${stripeUserPath}/${userId}`).get();
const userData = userDoc.data();
if (!userData || !userData["customer"]) {
throw new functions.https.HttpsError("not-found", "The customer id is not found.");
}
let defaultPayment = userData["defaultPayment"];
if (!defaultPayment) {
const customer = yield stripeClient.customers.retrieve(userData["customer"]);
defaultPayment = customer.invoice_settings.default_payment_method;
if (!defaultPayment) {
const payments = yield firestoreInstance.collection(`${stripeUserPath}/${userId}/${stripePaymentPath}`).get();
if (payments.size <= 0) {
throw new functions.https.HttpsError("not-found", "The payment method is not found.");
}
defaultPayment = payments.docs[0].data()["id"];
}
const update = {};
update["defaultPayment"] = defaultPayment;
yield userDoc.ref.set(update, {
merge: true,
});
}
const user = yield authInstance.getUser(userId);
if (!user) {
throw new functions.https.HttpsError("not-found", "The user is not found.");
}
let email = user.email;
if (!email) {
const paymentMethod = yield stripeClient.paymentMethods.retrieve(defaultPayment);
if (paymentMethod && paymentMethod["billing_details"] && paymentMethod["billing_details"]["email"]) {
email = paymentMethod["billing_details"]["email"];
}
if (!email) {
throw new functions.https.HttpsError("not-found", "The user's email is not found.");
}
}
const paymentIntent = yield stripeClient.paymentIntents.create({
payment_method_types: ["card"],
amount: amount,
confirm: false,
capture_method: "manual",
payment_method: defaultPayment,
description: "",
customer: userData["customer"],
receipt_email: email,
currency: currency !== null && currency !== void 0 ? currency : "usd",
setup_future_usage: "off_session",
});
if (!paymentIntent) {
throw new functions.https.HttpsError("data-loss", "The payment is failed.");
}
const confirmedPaymentIntent = yield stripeClient.paymentIntents.confirm(paymentIntent.id, {
return_url: returnUrl,
});
const nextActionUrl = (_l = (_k = (_j = confirmedPaymentIntent.next_action) === null || _j === void 0 ? void 0 : _j.redirect_to_url) === null || _k === void 0 ? void 0 : _k.url) !== null && _l !== void 0 ? _l : "";
if (nextActionUrl && !online) {
if (emailFrom && email && emailTitle && emailContent) {
switch (stripeEmailProvider) {
case "gmail": {
yield gmail.send({
from: emailFrom,
to: email,
title: emailTitle,
content: emailContent.replace("{url}", nextActionUrl),
});
break;
}
case "sendgrid": {
yield sendgrid.send({
from: emailFrom,
to: email,
title: emailTitle,
content: emailContent.replace("{url}", nextActionUrl),
});
break;
}
}
}
else {
throw new functions.https.HttpsError("unavailable", "3D Secure authentication is required, but the user is offline and no email settings have been configured.");
}
}
return {
url: online ? nextActionUrl : "",
returnUrl: online ? (_p = (_o = (_m = confirmedPaymentIntent.next_action) === null || _m === void 0 ? void 0 : _m.redirect_to_url) === null || _o === void 0 ? void 0 : _o.return_url) !== null && _p !== void 0 ? _p : "" : "",
authorizedId: paymentIntent.id,
};
}
case "confirm_authorization": {
const authorizedId = query.data.authorizedId;
if (!authorizedId) {
throw new functions.https.HttpsError("invalid-argument", "The authorized id is empty.");
}
yield stripeClient.paymentIntents.cancel(authorizedId);
return {
success: true,
};
}
case "create_purchase": {
const authInstance = admin.auth();
const amount = parseFloat(query.data.amount);
const revenue = parseFloat((_q = query.data.revenueRatio) !== null && _q !== void 0 ? _q : 0);
const currency = (_r = query.data.currency) !== null && _r !== void 0 ? _r : "jpy";
const userId = query.data.userId;
const targetUserId = query.data.targetUserId;
const orderId = query.data.orderId;
const description = query.data.description;
const emailFrom = query.data.emailFrom;
const emailTitle = query.data.emailTitle;
const emailContent = query.data.emailContent;
const locale = query.data.locale;
if (!orderId) {
throw new functions.https.HttpsError("invalid-argument", "The order id is empty.");
}
if (!userId) {
throw new functions.https.HttpsError("invalid-argument", "The user id is empty.");
}
const userDoc = yield firestoreInstance.doc(`${stripeUserPath}/${userId}`).get();
const userData = userDoc.data();
if (!userData || !userData["customer"]) {
throw new functions.https.HttpsError("not-found", "The customer id is not found.");
}
let defaultPayment = userData["defaultPayment"];
if (!defaultPayment) {
const customer = yield stripeClient.customers.retrieve(userData["customer"]);
defaultPayment = customer.invoice_settings.default_payment_method;
if (!defaultPayment) {
const payments = yield firestoreInstance.collection(`${stripeUserPath}/${userId}/${stripePaymentPath}`).get();
if (payments.size <= 0) {
throw new functions.https.HttpsError("not-found", "The payment method is not found.");
}
defaultPayment = payments.docs[0].data()["id"];
}
const update = {};
update["defaultPayment"] = defaultPayment;
yield userDoc.ref.set(update, {
merge: true,
});
}
const user = yield authInstance.getUser(userId);
if (!user) {
throw new functions.https.HttpsError("not-found", "The user is not found.");
}
let email = user.email;
if (!email) {
const paymentMethod = yield stripeClient.paymentMethods.retrieve(defaultPayment);
if (paymentMethod && paymentMethod["billing_details"] && paymentMethod["billing_details"]["email"]) {
email = paymentMethod["billing_details"]["email"];
}
if (!email) {
throw new functions.https.HttpsError("not-found", "The user's email is not found.");
}
}
if (targetUserId) {
const targetDoc = yield firestoreInstance.doc(`${stripeUserPath}/${targetUserId}`).get();
const targetData = targetDoc.data();
if (!targetData || !targetData["account"]) {
throw new functions.https.HttpsError("not-found", "The target data is not found.");
}
const paymentIntent = yield stripeClient.paymentIntents.create({
payment_method_types: ["card"],
amount: amount,
confirm: false,
capture_method: "manual",
payment_method: defaultPayment,
description: description,
customer: userData["customer"],
metadata: {
"order_id": orderId,
},
receipt_email: email,
currency: currency,
setup_future_usage: "off_session",
application_fee_amount: amount * revenue,
transfer_data: {
destination: targetData["account"],
},
});
if (!paymentIntent) {
throw new functions.https.HttpsError("data-loss", "The payment is failed.");
}
const update = {};
update["@uid"] = orderId;
update["orderId"] = orderId;
update["purchaseId"] = paymentIntent.id;
update["paymentMethodId"] = defaultPayment;
update["confirm"] = false;
update["verify"] = false;
update["capture"] = false;
update["success"] = false;
update["user"] = userId;
update["target"] = targetUserId;
update["nextAction"] = {
url: (_u = (_t = (_s = paymentIntent.next_action) === null || _s === void 0 ? void 0 : _s.redirect_to_url) === null || _t === void 0 ? void 0 : _t.url) !== null && _u !== void 0 ? _u : "",
returnUrl: (_x = (_w = (_v = paymentIntent.next_action) === null || _v === void 0 ? void 0 : _v.redirect_to_url) === null || _w === void 0 ? void 0 : _w.return_url) !== null && _x !== void 0 ? _x : "",
};
update["targetAccount"] = targetData["account"];
update["customer"] = userData["customer"];
update["amount"] = paymentIntent.amount;
update["application"] = paymentIntent.application;
update["applicationFeeAmount"] = paymentIntent.application_fee_amount;
update["transferAmount"] = (_z = (_y = paymentIntent.transfer_data) === null || _y === void 0 ? void 0 : _y.amount) !== null && _z !== void 0 ? _z : 0;
update["transferDistination"] = (_1 = (_0 = paymentIntent.transfer_data) === null || _0 === void 0 ? void 0 : _0.destination) !== null && _1 !== void 0 ? _1 : "";
update["currency"] = paymentIntent.currency;
update["clientSecret"] = paymentIntent.client_secret;
update["createdTime"] = new Date(paymentIntent.created * 1000);
update["updatedTime"] = new Date();
update["emailFrom"] = emailFrom;
update["emailTo"] = email;
update["emailTitle"] = emailTitle;
update["emailContent"] = emailContent;
update["locale"] = locale;
yield firestoreInstance.doc(`${stripeUserPath}/${userId}/${stripePurchasePath}/${orderId}`).set(update, {
merge: true,
});
return {
purchaseId: paymentIntent.id,
};
}
else {
const paymentIntent = yield stripeClient.paymentIntents.create({
payment_method_types: ["card"],
amount: amount,
confirm: false,
capture_method: "manual",
payment_method: defaultPayment,
description: description,
customer: userData["customer"],
metadata: {
"order_id": orderId,
},
receipt_email: email,
currency: currency,
setup_future_usage: "off_session",
});
if (!paymentIntent) {
throw new functions.https.HttpsError("data-loss", "The payment is failed.");
}
const update = {};
update["@uid"] = orderId;
update["orderId"] = orderId;
update["purchaseId"] = paymentIntent.id;
update["paymentMethodId"] = defaultPayment;
update["confirm"] = false;
update["verify"] = false;
update["capture"] = false;
update["success"] = false;
update["user"] = userId;
update["nextAction"] = {
url: (_4 = (_3 = (_2 = paymentIntent.next_action) === null || _2 === void 0 ? void 0 : _2.redirect_to_url) === null || _3 === void 0 ? void 0 : _3.url) !== null && _4 !== void 0 ? _4 : "",
returnUrl: (_7 = (_6 = (_5 = paymentIntent.next_action) === null || _5 === void 0 ? void 0 : _5.redirect_to_url) === null || _6 === void 0 ? void 0 : _6.return_url) !== null && _7 !== void 0 ? _7 : "",
};
update["customer"] = userData["customer"];
update["amount"] = paymentIntent.amount;
update["application"] = paymentIntent.application;
update["applicationFeeAmount"] = paymentIntent.application_fee_amount;
update["transferAmount"] = (_9 = (_8 = paymentIntent.transfer_data) === null || _8 === void 0 ? void 0 : _8.amount) !== null && _9 !== void 0 ? _9 : 0;
update["transferDistination"] = (_11 = (_10 = paymentIntent.transfer_data) === null || _10 === void 0 ? void 0 : _10.destination) !== null && _11 !== void 0 ? _11 : "";
update["currency"] = paymentIntent.currency;
update["clientSecret"] = paymentIntent.client_secret;
update["createdTime"] = new Date(paymentIntent.created * 1000);
update["updatedTime"] = new Date();
update["emailFrom"] = emailFrom;
update["emailTo"] = email;
update["emailTitle"] = emailTitle;
update["emailContent"] = emailContent;
update["locale"] = locale;
yield firestoreInstance.doc(`${stripeUserPath}/${userId}/${stripePurchasePath}/${orderId}`).set(update, {
merge: true,
});
return {
purchaseId: paymentIntent.id,
};
}
}
case "confirm_purchase": {
const userId = query.data.userId;
const orderId = query.data.orderId;
const successUrl = query.data.successUrl;
const failureUrl = query.data.failureUrl;
let returnUrl = query.data.returnUrl;
const online = query.data.online == "true";
if (!orderId) {
throw new functions.https.HttpsError("invalid-argument", "The order id is empty.");
}
if (!userId) {
throw new functions.https.HttpsError("inval