Hook: mam_pmt_charge_card

Signature

$result = apply_filters( 'mam_pmt_charge_card', array $data_array );

mam-stripe-manager implements this suite-wide payment filter (priority 10): it charges the customer’s saved card and returns the same array augmented with the outcome. Callers in the suite include MAM WooCommerce checkout/order capture, MAM WooCommerce Product Vendors (tips, held-payment capture), and the commission manager.

Trust boundary: apply this filter only from trusted server-side code with server-derived amounts. It moves real money.

Input keys

Key Type Required Meaning
payment_method string yes Must be 'stripe'. Any other value makes this plugin return the array untouched (so another processor can claim it). The key is removed before the result is returned.
post_id int recommended WooCommerce order id. Enables the amount ceiling, duplicate-intent reuse, idempotency keys, order currency, and order-meta persistence.
amount float yes Charge amount in decimal currency units (e.g. dollars). Zero-decimal currencies (JPY, KRW, …) are converted correctly.
customer_id int yes WordPress user id. The charge uses this user’s Stripe customer and their saved default payment method (_tsl_mam_stripe_payment_method user meta). Missing payment method → status = false.
capture string no 'no' creates an authorization hold (manual capture, PaymentIntent status requires_capture); anything else captures immediately.
last_charge_id string no An existing pi_… id: instead of creating a new intent, capture this one for amount. The intent’s wp_order_id metadata must match post_id (mismatch refuses the capture).
is_tip bool no Truthy marks the charge as a tip: the order-total amount ceiling and the duplicate-intent reuse are skipped (a second tip on the same order is a new, legitimate charge), and the idempotency key is tip-scoped.
statement_descriptor string no Overrides the charge description (default: vendor/site name + “Order {id}”; also used as the statement-descriptor suffix, truncated to 22 chars).

Amount bounds

  • amount <= 0 is a no-op: status is true only when the order total is also ≤ 0 (a genuinely free order); otherwise false — a lost/tampered amount is not silently “successful”.
  • For non-tip charges with an order, amount may not exceed order_total × tolerance + 0.01. The tolerance defaults to 1.2 because the checkout hold flow authorizes 120% of the order total, and is filterable:
apply_filters( 'mam_pmt_charge_amount_tolerance', 1.2 ); // return a float multiplier

Charges above the ceiling are refused (status = false, logged) without contacting Stripe.

Return shape

The input array, plus:

Key Type Meaning
status bool true when the PaymentIntent status is succeeded or requires_capture (a successful hold).
charge StripePaymentIntent|null The intent on success; null on refusal/failure.
error_message string Present only when a Stripe/API exception occurred — the exception message. (Legacy consumers may still read global $strip_error; new code should use error_message or the service’s last_error property.)

Built-in safety (no caller action needed)

  • Duplicate-submission guard — if the order already holds an intent for the same amount that succeeded (or an open hold when creating another hold), it is reused instead of charging again.
  • Stripe idempotency key — derived from order/amount/currency/capture-mode/payment-method/attempt, so a network retry maps to the original intent.
  • On success the order is stamped: transaction id, _mam_stripe_intent_id, _stripe_charge_ids, _stripe_currency, _stripe_source_id, _stripe_charge_captured, _mam_payment_method, and paid-date meta (HPOS-safe CRUD writes).

Example — charge an order’s total

$order = wc_get_order( $order_id );

$result = apply_filters( 'mam_pmt_charge_card', array(
    'payment_method' => 'stripe',
    'post_id'        => $order->get_id(),
    'customer_id'    => $order->get_customer_id(),
    'amount'         => (float) $order->get_total(),
    'capture'        => 'yes',
) );

if ( empty( $result['status'] ) ) {
    $reason = $result['error_message'] ?? 'charge refused';
    // mark the order failed, surface $reason
} else {
    $intent_id = $result['charge']->id; // pi_...
}

Example — hold now, capture later

// 1. At checkout: hold 120% of the total
$hold = apply_filters( 'mam_pmt_charge_card', array(
    'payment_method' => 'stripe',
    'post_id'        => $order_id,
    'customer_id'    => $user_id,
    'amount'         => $total * 1.2,
    'capture'        => 'no',          // authorization hold
) );

// 2. At fulfillment: capture the real amount from the held intent
$capture = apply_filters( 'mam_pmt_charge_card', array(
    'payment_method' => 'stripe',
    'post_id'        => $order_id,
    'customer_id'    => $user_id,
    'amount'         => $total,
    'last_charge_id' => $hold['charge']->id,
) );


Metadata

Field Value
Article type Hook Reference
Plugin slug mam-stripe-manager
Applies to plugin version 26.19.1+
Category Extending MAM Suite
Hook type filter (implemented by this plugin; applied by callers)
Audience PHP developer
Last verified 2026-06-10
Contents

    Need Support?

    Can't find the answer you're looking for? Don't worry we're here to help!