141 lines
3.2 KiB
TypeScript
141 lines
3.2 KiB
TypeScript
import Stripe from "stripe";
|
|
import { ENV } from "./_core/env";
|
|
|
|
// Initialize Stripe with secret key
|
|
export const stripe = new Stripe(ENV.stripeSecretKey || "", {
|
|
apiVersion: "2024-12-18.acacia" as any,
|
|
});
|
|
|
|
// Product definitions for bounty escrow
|
|
export const PRODUCTS = {
|
|
BOUNTY_ESCROW: {
|
|
name: "悬赏赏金托管",
|
|
description: "悬赏任务赏金托管服务",
|
|
},
|
|
};
|
|
|
|
// Create a checkout session for bounty escrow
|
|
export async function createBountyEscrowCheckout({
|
|
bountyId,
|
|
bountyTitle,
|
|
amount,
|
|
userId,
|
|
userEmail,
|
|
userName,
|
|
origin,
|
|
}: {
|
|
bountyId: number;
|
|
bountyTitle: string;
|
|
amount: number; // Amount in CNY cents
|
|
userId: number;
|
|
userEmail: string;
|
|
userName: string;
|
|
origin: string;
|
|
}) {
|
|
const session = await stripe.checkout.sessions.create({
|
|
mode: "payment",
|
|
payment_method_types: ["card"],
|
|
customer_email: userEmail,
|
|
client_reference_id: userId.toString(),
|
|
metadata: {
|
|
user_id: userId.toString(),
|
|
bounty_id: bountyId.toString(),
|
|
customer_email: userEmail,
|
|
customer_name: userName,
|
|
type: "bounty_escrow",
|
|
},
|
|
line_items: [
|
|
{
|
|
price_data: {
|
|
currency: "cny",
|
|
product_data: {
|
|
name: `悬赏托管: ${bountyTitle}`,
|
|
description: `悬赏ID: ${bountyId}`,
|
|
},
|
|
unit_amount: amount, // Amount in cents
|
|
},
|
|
quantity: 1,
|
|
},
|
|
],
|
|
allow_promotion_codes: true,
|
|
success_url: `${origin}/bounties/${bountyId}?payment=success`,
|
|
cancel_url: `${origin}/bounties/${bountyId}?payment=cancelled`,
|
|
});
|
|
|
|
return session;
|
|
}
|
|
|
|
// Create a Stripe Connect account for accepting payments
|
|
export async function createConnectAccount({
|
|
userId,
|
|
email,
|
|
}: {
|
|
userId: number;
|
|
email: string;
|
|
}) {
|
|
const account = await stripe.accounts.create({
|
|
type: "express",
|
|
email,
|
|
metadata: {
|
|
user_id: userId.toString(),
|
|
},
|
|
capabilities: {
|
|
card_payments: { requested: true },
|
|
transfers: { requested: true },
|
|
},
|
|
});
|
|
|
|
return account;
|
|
}
|
|
|
|
// Create an account link for onboarding
|
|
export async function createAccountLink({
|
|
accountId,
|
|
origin,
|
|
}: {
|
|
accountId: string;
|
|
origin: string;
|
|
}) {
|
|
const accountLink = await stripe.accountLinks.create({
|
|
account: accountId,
|
|
refresh_url: `${origin}/dashboard?stripe=refresh`,
|
|
return_url: `${origin}/dashboard?stripe=success`,
|
|
type: "account_onboarding",
|
|
});
|
|
|
|
return accountLink;
|
|
}
|
|
|
|
// Transfer funds to connected account
|
|
export async function transferToConnectedAccount({
|
|
amount,
|
|
destinationAccountId,
|
|
bountyId,
|
|
}: {
|
|
amount: number; // Amount in cents
|
|
destinationAccountId: string;
|
|
bountyId: number;
|
|
}) {
|
|
const transfer = await stripe.transfers.create({
|
|
amount,
|
|
currency: "cny",
|
|
destination: destinationAccountId,
|
|
metadata: {
|
|
bounty_id: bountyId.toString(),
|
|
type: "bounty_payout",
|
|
},
|
|
});
|
|
|
|
return transfer;
|
|
}
|
|
|
|
// Get account status
|
|
export async function getAccountStatus(accountId: string) {
|
|
const account = await stripe.accounts.retrieve(accountId);
|
|
return {
|
|
chargesEnabled: account.charges_enabled,
|
|
payoutsEnabled: account.payouts_enabled,
|
|
detailsSubmitted: account.details_submitted,
|
|
};
|
|
}
|