Loading...
Loading...
Payment support based on Stripe, supporting credit cards and debit cards
npx skill4agent add caffeinelabs/skills extension-stripemo:caffeineai-stripe/stripe.moimport OutCall "mo:caffeineai-http-outcalls/outcall";
module {
public type StripeConfiguration = {
secretKey : Text;
allowedCountries : [Text];
};
public type ShoppingItem = {
currency : Text;
productName : Text;
productDescription : Text;
priceInCents : Nat;
quantity : Nat;
};
/// Initiate payment session for shopping items.
/// Returns Stripe JSON reply message.
public func createCheckoutSession(configuration : StripeConfiguration, caller : Principal, items : [ShoppingItem], successUrl : Text, cancelUrl : Text, transform : OutCall.Transform) : async Text;
public type StripeSessionStatus = {
#failed : { error : Text };
#completed : { response : Text; userPrincipal : ?Text };
};
/// Check payment status.
public func getSessionStatus(configuration : StripeConfiguration, sessionId : Text, transform : OutCall.Transform) : async StripeSessionStatus;
};import Stripe "mo:caffeineai-stripe/stripe";
import AccessControl "mo:caffeineai-authorization/access-control";
import MixinAuthorization "mo:caffeineai-authorization/MixinAuthorization";
import OutCall "mo:caffeineai-http-outcalls/outcall";
import Map "mo:core/Map";
import Iter "mo:core/Iter";
import Text "mo:core/Text";
import Runtime "mo:core/Runtime";
actor {
// Include authorization
let accessControlState = AccessControl.initState();
include MixinAuthorization(accessControlState);
// Shopping data
public type Product = {
id : Text;
// add custom fields
};
let products = Map.empty<Text, Product>();
public query func getProducts() : async [Product] {
products.values().toArray();
};
public shared ({ caller }) func addProduct(product : Product) : async () {
if (not (AccessControl.hasPermission(accessControlState, caller, #admin))) {
Runtime.trap("Unauthorized: Only admins can add products");
};
products.add(product.id, product);
};
public shared ({ caller }) func updateProduct(product : Product) : async () {
if (not (AccessControl.hasPermission(accessControlState, caller, #admin))) {
Runtime.trap("Unauthorized: Only admins can update products");
};
products.add(product.id, product);
};
public shared ({ caller }) func deleteProduct(productId : Text) : async () {
if (not (AccessControl.hasPermission(accessControlState, caller, #admin))) {
Runtime.trap("Unauthorized: Only admins can delete products");
};
products.remove(productId);
};
// Stripe integration
var configuration : ?Stripe.StripeConfiguration = null;
public query func isStripeConfigured() : async Bool {
configuration != null;
};
public shared ({ caller }) func setStripeConfiguration(config : Stripe.StripeConfiguration) : async () {
if (not (AccessControl.hasPermission(accessControlState, caller, #admin))) {
Runtime.trap("Unauthorized: Only admins can perform this action");
};
configuration := ?config;
};
func getStripeConfiguration() : Stripe.StripeConfiguration {
switch (configuration) {
case (null) { Runtime.trap("Stripe needs to be first configured") };
case (?value) { value };
};
};
public func getStripeSessionStatus(sessionId : Text) : async Stripe.StripeSessionStatus {
await Stripe.getSessionStatus(getStripeConfiguration(), sessionId, transform);
};
public shared ({ caller }) func createCheckoutSession(items : [Stripe.ShoppingItem], successUrl : Text, cancelUrl : Text) : async Text {
await Stripe.createCheckoutSession(getStripeConfiguration(), caller, items, successUrl, cancelUrl, transform);
};
public query func transform(input : OutCall.TransformationInput) : async OutCall.TransformationOutput {
OutCall.transform(input);
};
// Add more data and functions as needed
};isStripeConfigured()setStripeConfiguration()StripeConfigurationcreateCheckoutSessionurlimport { useMutation } from '@tanstack/react-query';
import { useActor } from '@caffeineai/core-infrastructure';
import { ShoppingItem } from '../backend';
export type CheckoutSession = {
id: string;
url: string;
};
export function useCreateCheckoutSession() {
const { actor } = useActor();
return useMutation({
mutationFn: async (items: ShoppingItem[]): Promise<CheckoutSession> => {
if (!actor) throw new Error('Actor not available');
const baseUrl = `${window.location.protocol}//${window.location.host}`;
const successUrl = `${baseUrl}/payment-success`;
const cancelUrl = `${baseUrl}/payment-failure`;
const result = await actor.createCheckoutSession(items, successUrl, cancelUrl);
// JSON parsing is important!
const session = JSON.parse(result) as CheckoutSession;
if (!session?.url) {
throw new Error('Stripe session missing url');
}
return session;
}
});
}useCreateCheckoutSession()ShoppingItem[]CheckoutSessionCheckoutSessionwindow.location.href/undefinedsession.urlconst session = await createCheckoutSession.mutateAsync(shoppingItems);
if (!session?.url) throw new Error('Stripe session missing url');
window.location.href = session.url;