Create payment-token-api.md (#40761)

* Create payment-token-api.md

* Create payment-gateway-api.md

* adjusting for lint

* Create payment-gateway-plugin-base.md

* Update payment-token-api.md

* Update payment-token-api.md

* adjusting for linting

* Update payment-gateway-api.md
This commit is contained in:
Brent MacKinnon 2023-10-23 18:00:42 -03:00 committed by GitHub
parent 890fb93a01
commit 9a10a416b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 896 additions and 0 deletions

View File

@ -0,0 +1,252 @@
# Payment Gateway API
Payment gateways in WooCommerce are class based and can be added through traditional plugins. This guide provides an intro to gateway development.
**Note:** We are unable to provide support for customizations under our **[Support Policy](http://www.woocommerce.com/support-policy/)**. If you need to further customize a snippet, or extend its functionality, we highly recommend [**Codeable**](https://codeable.io/?ref=z4Hnp), or a [**Certified WooExpert**](https://woocommerce.com/experts/).
## Types of payment gateway
Payment gateways come in several varieties:
1. **Form based** This is where the user must click a button on a form that then redirects them to the payment processor on the gateways own website. _Example_: PayPal standard, Authorize.net DPM
2. **iFrame based** This is when the gateway payment system is loaded inside an iframe on your store. _Example_: SagePay Form, PayPal Advanced
3. **Direct** This is when the payment fields are shown directly on the checkout page and the payment is made when place order is pressed. _Example_: PayPal Pro, Authorize.net AIM
4. **Offline** No online payment is made. _Example_: Cheque, Bank Transfer
Form and iFrame based gateways post data offsite, meaning there are less security issues for you to think about. Direct gateways, however, require server security to be implemented ([SSL certificates](https://woocommerce.com/document/ssl-and-https/), etc.) and may also require a level of [PCI compliance](https://woocommerce.com/document/pci-dss-compliance-and-woocommerce/).
## Creating a basic payment gateway
**Note:** We are unable to provide support for customizations under our [Support Policy](http://www.woocommerce.com/support-policy/). If you are unfamiliar with code/templates and resolving potential conflicts, select a [WooExpert or Developer](https://woocommerce.com/customizations/)  for assistance.
**Note:** The instructions below are for the default Checkout page. If youre looking to add a custom payment method for the new Checkout block, check out [this documentation.](https://github.com/woocommerce/woocommerce-blocks/blob/trunk/docs/third-party-developers/extensibility/checkout-payment-methods/payment-method-integration.md)
Payment gateways should be created as additional plugins that hook into WooCommerce. Inside the plugin, you need to create a class after plugins are loaded. Example:
``` php
add_action( 'plugins_loaded', 'init_your_gateway_class' );
```
It is also important that your gateway class extends the WooCommerce base gateway class, so you have access to important methods and the [settings API](https://woocommerce.com/document/settings-api/ "https://woocommerce.com/document/settings-api/"):
``` php
function init_your_gateway_class() {
class WC_Gateway_Your_Gateway extends WC_Payment_Gateway {}
}
```
You can view the [WC_Payment_Gateway class in the API Docs](https://woocommerce.github.io/code-reference/classes/WC-Payment-Gateway.html).
As well as defining your class, you need to also tell WooCommerce (WC) that it exists. Do this by filtering _woocommerce_payment_gateways_:
``` php
function add_your_gateway_class( $methods ) {
$methods\[\] = 'WC_Gateway_Your_Gateway';
return $methods;
}
```
``` php
add_filter( 'woocommerce_payment_gateways', 'add_your_gateway_class' );
```
### Required Methods
Most methods are inherited from the WC_Payment_Gateway class, but some are required in your custom gateway.
#### \_\_construct()
Within your constructor, you should define the following variables:
- `$this->id` Unique ID for your gateway, e.g., your_gateway
- `$this->icon` If you want to show an image next to the gateways name on the frontend, enter a URL to an image.
- `$this->has_fields` Bool. Can be set to true if you want payment fields to show on the checkout (if doing a direct integration).
- `$this->method_title` Title of the payment method shown on the admin page.
- `$this->method_description` Description for the payment method shown on the admin page.
Your constructor should also define and load settings fields:
``` php
$this->init\_form\_fields();
$this->init_settings();
```
Well cover `init_form_fields()` later, but this basically defines your settings that are then loaded with `init_settings()`.
After `init_settings()` is called, you can get the settings and load them into variables, meaning:
``` php
$this->title = $this->get_option( 'title' );
```
Finally, you need to add a save hook for your settings:
``` php
add_action( 'woocommerce_update_options_payment_gateways\_' . $this->id, array( $this, 'process_admin_options' ) );
```
#### init_form_fields()
Use this method to set `$this->form_fields` these are options youll show in admin on your gateway settings page and make use of the [WC Settings API](https://woocommerce.com/document/settings-api/ "https://woocommerce.com/document/settings-api/").
A basic set of settings for your gateway would consist of _enabled_, _title_ and _description_:
``` php
$this->form_fields = array(
'enabled' => array(
'title' => \_\_( 'Enable/Disable', 'woocommerce' ),
'type' => 'checkbox',
'label' => \_\_( 'Enable Cheque Payment', 'woocommerce' ),
'default' => 'yes'
),
'title' => array(
'title' => \_\_( 'Title', 'woocommerce' ),
'type' => 'text',
'description' => \_\_( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
'default' => \_\_( 'Cheque Payment', 'woocommerce' ),
'desc_tip' => true,
),
'description' => array(
'title' => \_\_( 'Customer Message', 'woocommerce' ),
'type' => 'textarea',
'default' => ''
)
);
```
#### process_payment( $order_id )
Now for the most important part of the gateway — handling payment and processing the order. Process_payment also tells WC where to redirect the user, and this is done with a returned array.
Here is an example of a process_payment function from the Cheque gateway:
``` php
function process_payment( $order_id ) {
global $woocommerce;
$order = new WC_Order( $order_id );
// Mark as on-hold (we're awaiting the cheque)
$order->update\_status('on-hold', \_\_( 'Awaiting cheque payment', 'woocommerce' ));
// Remove cart
$woocommerce->cart->empty\_cart();
// Return thankyou redirect
return array(
'result' => 'success',
'redirect' => $this->get\_return\_url( $order )
);
}
```
As you can see, its job is to:
- Get and update the order being processed
- Return success and redirect URL (in this case the thanks page)
Cheque gives the order On-Hold status since the payment cannot be verified automatically. If, however, you are building a direct gateway, then you can complete the order here instead. Rather than using update_status when an order is paid, you should use payment_complete:
``` php
$order->payment_complete();
```
This ensures stock reductions are made, and the status is changed to the correct value.
If payment fails, you should throw an error and return null:
``` php
wc_add_notice( \_\_('Payment error:', 'woothemes') . $error_message, 'error' );
return;
```
WooCommerce will catch this error and show it on the checkout page.
Stock levels are updated via actions (`woocommerce_payment_complete` and in transitions between order statuses), so its no longer needed to manually call the methods reducing stock levels while processing the payment.
### Updating Order Status and Adding Notes
Updating the order status can be done using functions in the order class. You should only do this if the order status is not processing (in which case you should use payment_complete()). An example of updating to a custom status would be:
``` php
$order = new WC\_Order( $order\_id );
$order->update_status('on-hold', \_\_('Awaiting cheque payment', 'woothemes'));
```
The above example updates the status to On-Hold and adds a note informing the owner that it is awaiting a Cheque. You can add notes without updating the order status; this is used for adding a debug message:
``` php
$order->add_order_note( \_\_('IPN payment completed', 'woothemes') );
```
### Order Status Best Practice
- If the order has completed but the admin needs to manually verify payment, use **On-Hold**
- If the order fails and has already been created, set to **Failed**
- If payment is complete, let WooCommerce handle the status and use `$order->payment_complete()`. WooCommerce will use either **Completed** or **Processing** status and handle stock.
## Notes on Direct Gateways
If you are creating an advanced, direct gateway (i.e., one that takes payment on the actual checkout page), there are additional steps involved. First, you need to set has_fields to true in the gateway constructor:
``` php
$this->has_fields = true;
```
This tells the checkout to output a payment_box containing your direct payment form that you define next.
Create a method called `payment_fields()` this contains your form, most likely to have credit card details.
The next but optional method to add is `validate_fields()`. Return true if the form passes validation or false if it fails. You can use the `wc_add_notice()` function if you want to add an error and display it to the user.
Finally, you need to add payment code inside your `process_payment( $order_id )` method. This takes the posted form data and attempts payment directly via the payment provider.
If payment fails, you should output an error and return nothing:
``` php
wc_add_notice( \_\_('Payment error:', 'woothemes') . $error_message, 'error' );
return;
```
If payment is successful, you should set the order as paid and return the success array:
``` php
// Payment complete
$order->payment_complete();
```
``` php
// Return thank you page redirect
return array(
'result' => 'success',
'redirect' => $this->get_return_url( $order )
);
```
## Working with Payment Gateway Callbacks (such as PayPal IPN)
If you are building a gateway that makes a callback to your store to tell you about the status of an order, you need to add code to handle this inside your gateway.
The best way to add a callback and callback handler is to use WC-API hooks. An example would be as PayPal Standard does. It sets the callback/IPN URL as:
``` php
str_replace( 'https:', 'http:', add_query_arg( 'wc-api', 'WC_Gateway_Paypal', home_url( '/' ) ) );
```
Then hooks in its handler to the hook:
``` php
add_action( 'woocommerce_api_wc_gateway_paypal', array( $this, 'check_ipn_response' ) );
```
WooCommerce will call your gateway and run the action when the URL is called.
For more information, see [WC_API — The WooCommerce API Callback](https://woocommerce.com/document/wc_api-the-woocommerce-api-callback/).
## Hooks in Gateways
Its important to note that adding hooks inside gateway classes may not trigger. Gateways are only loaded when needed, such as during checkout and on the settings page in admin.
You should keep hooks outside of the class or use WC-API if you need to hook into WordPress events from your class.

View File

@ -0,0 +1,45 @@
# WooCommerce payment gateway plugin base
This code can be used as a base to create your own simple custom payment gateway for WooCommerce. If not used in a custom plugin, you need to add this code to your child themes functions.php file or via a plugin that allows custom functions to be added, such as the [Code snippets](https://wordpress.org/plugins/code-snippets/) plugin. Please dont add custom code directly to your parent themes functions.php file as this will be wiped entirely when you update the theme.
``` php
<?php
/*
Plugin Name: WooCommerce <enter name> Gateway
Plugin URI: http://woothemes.com/woocommerce
Description: Extends WooCommerce with an <enter name> gateway.
Version: 1.0
Author: WooThemes
Author URI: http://woothemes.com/
Copyright: © 2009-2011 WooThemes.
License: GNU General Public License v3.0
License URI: http://www.gnu.org/licenses/gpl-3.0.html
*/
add_action('plugins_loaded', 'woocommerce_gateway_name_init', 0);
function woocommerce_gateway_name_init() {
if ( !class_exists( 'WC_Payment_Gateway' ) ) return;
/**
* Localisation
*/
load_plugin_textdomain('wc-gateway-name', false, dirname( plugin_basename( __FILE__ ) ) . '/languages');
/**
* Gateway class
*/
class WC_Gateway_Name extends WC_Payment_Gateway {
// Go wild in here
}
/**
* Add the Gateway to WooCommerce
**/
function woocommerce_add_gateway_name_gateway($methods) {
$methods[] = 'WC_Gateway_Name';
return $methods;
}
add_filter('woocommerce_payment_gateways', 'woocommerce_add_gateway_name_gateway' );
}
```

View File

@ -0,0 +1,599 @@
# Payment Token API
WooCommerce 2.6 introduced an API for storing and managing payment tokens for gateways. Users can also manage these tokens from their account settings and choose from saved payment tokens on checkout.
This guide offers a few useful tutorials for using the new API as well as all the various methods available to you.
## Table Of Contents
* [Tutorials](#tutorials)
* [Adding Payment Token API Support To Your Gateway](#adding-payment-token-api-support-to-your-gateway)
* [Creating A New Token Type](#creating-a-new-token-type)
* [Classes](#classes)
* [WC_Payment_Tokens](#wc_payment_tokens)
* [WC_Payment_Token_CC](#wc_payment_token_cc)
* [WC_Payment_Token_eCheck](#wc_payment_token_echeck)
* [WC_Payment_Token](#wc_payment_token)
## Tutorials
### Adding Payment Token API Support To Your Gateway
We'll use the Simplify Commerce gateway in some of these examples.
#### Step 0: Extending The Correct Gateway Base
WooCommerce ships with two base classes for gateways. These classes were introduced along with the Token API in 2.6. They are `WC_Payment_Gateway_CC` (for credit card based tokens) and `WC_Payment_Gateway_eCheck` (for eCheck based tokens). They contain some useful code for generating payment forms on checkout and should hopefully cover most cases.
You can also implement your own gateway base by extending the abstract `WC_Payment_Gateway` class, if neither of those classes work for you.
Since Simplify deals with credit cards, we extend the credit card gateway.
`class WC_Gateway_Simplify_Commerce extends WC_Payment_Gateway_CC`
#### Step 1: 'Supports' Array
We need to tell WooCommerce our gateway supports tokenization. Like other gateways features, this is defined in a gateway's `__construct` in an array called `supports`.
Here is the Simplify array:
``` php
$this->supports = array(
'subscriptions',
'products',
...
'refunds',
'pre-orders',
);
```
Add `tokenization` to this array.
#### Step 2: Define A Method For Adding/Saving New Payment Methods From "My Account"
The form handler that is run when adding a new payment method from the "my accounts" section will call your gateway's `add_payment_method` method.
After any validation (i.e. making sure the token and data you need is present from the payment provider), you can start building a new token by creating an instance of one of the following classes: `WC_Payment_Token_CC` or `WC_Payment_Token_eCheck`. Like gateways, you can also extend the abstract `WC_Payment_Token` class and define your own token type type if necessary. For more information on all three of these classes and their methods, see further down below in this doc.
Since Simplify uses credit cards, we will use the credit card class.
`$token = new WC_Payment_Token_CC();`
We will use various `set_` methods to pass in information about our token. To start with we will pass the token string and the gateway ID so the token can be associated with Simplify.
``` php
$token->set_token( $token_string );
$token->set_gateway_id( $this->id ); // `$this->id` references the gateway ID set in `__construct`
```
At this point we can set any other necessary information we want to store with the token. Credit cards require a card type (visa, mastercard, etc), last four digits of the card number, an expiration month, and an expiration year.
``` php
$token->set_card_type( 'visa' );
$token->set_last4( '1234' );
$token->set_expiry_month( '12' );
$token->set_expiry_year( '2018' );
```
In most cases, you will also want to associate a token with a specific user:
`$token->set_user_id( get_current_user_id() );`
Finally, we can save our token to the database once the token object is built.
`$token->save();`
Save will return `true` if the token was successfully saved, and `false` if an error occurred (like a missing field).
#### Step 3: Save Methods On Checkout
WooCommerce also allows customers to save a new payment token during the checkout process in addition to "my account". You'll need to add some code to your gateways `process_payment` function to make this work correctly.
To figure out if you need to save a new payment method you can check the following POST field which should return `true` if the "Save to Account" checkbox was selected.
`wc-{$gateway_id}-new-payment-method`
If you have previously saved tokens being offered to the user, you can also look at `wc-{$gateway_id}-payment-token` for the value `new` to make sure the "Use a new card" / "Use new payment method" radio button was selected.
Once you have found out that a token should be saved you can save a token in the same way you did in Step 2, using the `set_` and `save` methods.
#### Step 4: Retrieve The Token When Processing Payments
You will need to retrieve a saved token when processing a payment in your gateway if a user selects one. This should also be done in your `process_payment` method.
You can check if an existing token should be used with a conditional like the following:
`if ( isset( $_POST['wc-simplify_commerce-payment-token'] ) && 'new' !== $_POST['wc-simplify_commerce-payment-token'] ) {`
`wc-{$gateway_id}}-payment-token` will return the ID of the selected token.
You can then load a token from ta ID (more on the WC_Payment_Tokens class later in this doc):
``` php
$token_id = wc_clean( $_POST['wc-simplify_commerce-payment-token'] );
$token = WC_Payment_Tokens::get( $token_id );
```
This does **not** check if the loaded token belongs to the current user. You can do that with a simple check:
``` php
// Token user ID does not match the current user... bail out of payment processing.
if ( $token->get_user_id() !== get_current_user_id() ) {
// Optionally display a notice with `wc_add_notice`
return;
}
```
Once you have loaded the token and done any necessary checks, you can get the actual token string (to pass to your payment provider) by using
`$token->get_token()`.
### Creating A New Token Type
You can extend the abstract WC_Payment_Token class and create a new token type If the provided eCheck and CC token types do not satisfy your requirements. There are a few things you need to include if you do this.
#### Step 0: Extend WC_Payment_Token And Name Your Type
Start by extending WC_Payment_Token and providing a name for the new type. We'll look at how the eCheck token class is built since it is the most basic token type shipped in WooCommerce core.
A barebones token file should look like this:
``` php
class WC_Payment_Token_eCheck extends WC_Payment_Token {
/** @protected string Token Type String */
protected $type = 'eCheck';
}
```
The name for this token type is 'eCheck'. The value provided in `$type` needs to match the class name (i.e: `WC_Payment_Token_$type`).
#### Step 1: Provide A Validate Method
Some basic validation is performed on a token before it is saved to the database. `WC_Payment_Token` checks to make sure the actual token value is set, as well as the `$type` defined above. If you want to validate the existence of other data (eChecks require the last 4 digits for example) or length (an expiry month should be 2 characters), you can provide your own `validate()` method.
Validate should return `true` if everything looks OK, and false if something doesn't.
Always make sure to call `WC_Payment_Token`'s validate method before adding in your own logic.
``` php
public function validate() {
if ( false === parent::validate() ) {
return false;
}
```
Now we can add some logic in for the "last 4" digits.
``` php
if ( ! $this->get_last4() ) {
return false;
}
```
Finally, return true if we make it to the end of the `validate()` method.
``` php
return true;
}
```
#### Step 2: Provide get\_ And set\_ Methods For Extra Data
You can now add your own methods for each piece of data you would like to expose. Handy functions are provided to you to make storing and retrieving data easy. All data is stored in a meta table so you do not need to make your own table or add new fields to an existing one.
Provide a `get_` and `set_` method for each piece of data you want to capture. For eChecks, this is "last4" for the last 4 digits of a check.
``` php
public function get_last4() {
return $this->get_meta( 'last4' );
}
public function set_last4( $last4 ) {
$this->add_meta_data( 'last4', $last4, true );
}
```
That's it! These meta functions are provided by [WC_Data](https://github.com/woothemes/woocommerce/blob/trunk/includes/abstracts/abstract-wc-data.php).
#### Step 3: Use Your New Token Type
You can now use your new token type, either directly when building a new token
``` php
`$token = new WC_Payment_Token_eCheck();`
// set token properties
$token->save()
```
or it will be returned when using `WC_Payment_Tokens::get( $token_id )`.
## Classes
### WC_Payment_Tokens
This class provides a set of helpful methods for interacting with payment tokens. All methods are static and can be called without creating an instance of the class.
#### get_customer_tokens( $customer_id, $gateway_id = '' )
Returns an array of token objects for the customer specified in `$customer_id`. You can filter by gateway by providing a gateway ID as well.
``` php
// Get all tokens for the current user
$tokens = WC_Payment_Tokens::get_customer_tokens( get_current_user_id() );
// Get all tokens for user 42
$tokens = WC_Payment_Tokens::get_customer_tokens( 42 );
// Get all Simplify tokens for the current user
$tokens = WC_Payment_Tokens::get_customer_tokens( get_current_user_id(), 'simplify_commerce' );
```
#### get_customer_default_token( $customer_id )
Returns a token object for the token that is marked as 'default' (the token that will be automatically selected on checkout). If a user does not have a default token/has no tokens, this function will return null.
``` php
// Get default token for the current user
$token = WC_Payment_Tokens::get_customer_default_token( get_current_user_id() );
// Get default token for user 520
$token = WC_Payment_Tokens::get_customer_default_token( 520 );
```
#### get_order_tokens( $order_id )
Orders can have payment tokens associated with them (useful for subscription products and renewing, for example). You can get a list of tokens associated with this function. Alternatively you can use `WC_Order`'s '`get_payment_tokens()` function to get the same result.
``` php
// Get tokens associated with order 25
$tokens = WC_Payment_Tokens::get_order_tokens( 25 );
// Get tokens associated with order 25, via WC_Order
$order = wc_get_order( 25 );
$tokens = $order->get_payment_tokens();
```
#### get( $token_id )
Returns a single payment token object for the provided `$token_id`.
``` php
// Get payment token 52
$token = WC_Payment_Tokens::get( 52 );
```
#### delete( $token_id )
Deletes the provided token.
``` php
// Delete payment token 52
WC_Payment_Tokens::delete( 52 );
```
#### set_users_default( $user_id, $token_id )
Makes the provided token (`$token_id`) the provided user (`$user_id`)'s default token. It makes sure that whatever token is currently set is default is removed and sets the new one.
``` php
// Set user 17's default token to token 82
WC_Payment_Tokens::set_users_default( 17, 82 );
```
#### get_token_type_by_id( $token_id )
You can use this function If you have a token's ID but you don't know what type of token it is (credit card, eCheck, ...).
``` php
// Find out that payment token 23 is a cc/credit card token
$type = WC_Payment_Tokens::get_token_type_by_id( 23 );
```
### WC_Payment_Token_CC
`set_` methods **do not** update the token in the database. You must call `save()`, `create()` (new tokens only), or `update()` (existing tokens only).
#### validate()
Makes sure the credit card token has the last 4 digits stored, an expiration year in the format YYYY, an expiration month with the format MM, the card type, and the actual token.
``` php
$token = new WC_Payment_Token_CC();
$token->set_token( 'token here' );
$token->set_last4( '4124' );
$token->set_expiry_year( '2017' );
$token->set_expiry_month( '1' ); // incorrect length
$token->set_card_type( 'visa' );
var_dump( $token->validate() ); // bool(false)
$token->set_expiry_month( '01' );
var_dump( $token->validate() ); // bool(true)
```
#### get_card_type()
Get the card type (visa, mastercard, etc).
``` php
$token = WC_Payment_Tokens::get( 42 );
echo $token->get_card_type();
```
#### set_card_type( $type )
Set the credit card type. This is a freeform text field, but the following values can be used and WooCommerce will show a formatted label New labels can be added with the `wocommerce_credit_card_type_labels` filter.
``` php
$token = WC_Payment_Tokens::get( 42 );
$token->set_last4( 'visa' );
echo $token->get_card_type(); // returns visa
```
Supported types/labels:
``` php
array(
'mastercard' => __( 'MasterCard', 'woocommerce' ),
'visa' => __( 'Visa', 'woocommerce' ),
'discover' => __( 'Discover', 'woocommerce' ),
'american express' => __( 'American Express', 'woocommerce' ),
'diners' => __( 'Diners', 'woocommerce' ),
'jcb' => __( 'JCB', 'woocommerce' ),
) );
```
#### get_expiry_year()
Get the card's expiration year.
``` php
$token = WC_Payment_Tokens::get( 42 );
echo $token->get_expiry_year;
```
#### set_expiry_year( $year )
Set the card's expiration year. YYYY format.
``` php
$token = WC_Payment_Tokens::get( 42 );
$token->set_expiry_year( '2018' );
echo $token->get_expiry_year(); // returns 2018
```
#### get_expiry_month()
Get the card's expiration month.
``` php
$token = WC_Payment_Tokens::get( 42 );
echo $token->get_expiry_month();
```
#### set_expiry_month( $month )
Set the card's expiration month. MM format.
``` php
$token = WC_Payment_Tokens::get( 42 );
$token->set_expiry_year( '12' );
echo $token->get_expiry_month(); // returns 12
```
#### get_last4()
Get the last 4 digits of the stored credit card number.
``` php
$token = WC_Payment_Tokens::get( 42 );
echo $token->get_last4();
```
#### set_last4( $last4 )
Set the last 4 digits of the stored credit card number.
``` php
$token = WC_Payment_Tokens::get( 42 );
$token->set_last4( '2929' );
echo $token->get_last4(); // returns 2929
```
### WC_Payment_Token_eCheck
`set_` methods **do not** update the token in the database. You must call `save()`, `create()` (new tokens only), or `update()` (existing tokens only).
#### validate()
Makes sure the eCheck token has the last 4 digits stored as well as the actual token.
``` php
$token = new WC_Payment_Token_eCheck();
$token->set_token( 'token here' );
var_dump( $token->validate() ); // bool(false)
$token->set_last4( '4123' );
var_dump( $token->validate() ); // bool(true)
```
#### get_last4()
Get the last 4 digits of the stored account number.
``` php
$token = WC_Payment_Tokens::get( 42 );
echo $token->get_last4();
```
#### set_last4( $last4 )
Set the last 4 digits of the stored credit card number.
``` php
$token = WC_Payment_Tokens::get( 42 );
$token->set_last4( '2929' );
echo $token->get_last4(); // returns 2929
```
### WC_Payment_Token
You should not use `WC_Payment_Token` directly. Use one of the bundled token classes (`WC_Payment_Token_CC` for credit cards and `WC_Payment_Token_eCheck`). You can extend this class if neither of those work for you. All the methods defined in this section are available to those classes.
`set_` methods **do not** update the token in the database. You must call `save()`, `create()` (new tokens only), or `update()` (existing tokens only).
#### get_id()
Get the token's ID.
``` php
// Get the token ID for user ID 26's default token
$token = WC_Payment_Tokens::get_customer_default_token( 26 );
echo $token->get_id();
```
#### get_token()
Get the actual token string (used to communicate with payment processors).
``` php
$token = WC_Payment_Tokens::get( 49 );
echo $token->get_token();
```
#### set_token( $token )
Set the token string.
``` php
// $api_token comes from an API request to a payment processor.
$token = WC_Payment_Tokens::get( 42 );
$token->set_token( $api_token );
echo $token->get_token(); // returns our token
```
#### get_type()
Get the type of token. CC or eCheck. This will also return any new types introduced.
``` php
$token = WC_Payment_Tokens::get( 49 );
echo $token->get_type();
```
#### get_user_id()
Get the user ID associated with the token.
``` php
$token = WC_Payment_Tokens::get( 49 );
if ( $token->get_user_id() === get_current_user_id() ) {
// This token belongs to the current user.
}
```
#### set_user_id( $user_id )
Associate a token with a user.
``` php
$token = WC_Payment_Tokens::get( 42 );
$token->set_user_id( '21' ); // This token now belongs to user 21.
echo $token->get_last4(); // returns 2929
```
#### get_gateway_id
Get the gateway associated with the token.
``` php
$token = WC_Payment_Tokens::get( 49 );
$token->get_gateway_id();
```
#### set_gateway_id( $gateway_id )
Set the gateway associated with the token. This should match the "ID" defined in your gateway. For example, 'simplify_commerce' is the ID for core's implementation of Simplify.
``` php
$token->set_gateway_id( 'simplify_commerce' );
echo $token->get_gateway_id();
```
#### is_default()
Returns true if the token is marked as a user's default. Default tokens are auto-selected on checkout.
``` php
$token = WC_Payment_Tokens::get( 42 ); // Token 42 is a default token for user 3
var_dump( $token->is_default() ); // returns true
$token = WC_Payment_Tokens::get( 43 ); // Token 43 is user 3's token, but not default
var_dump( $token->is_default() ); // returns false
```
#### set_default( $is_default )
Toggle a tokens 'default' flag. Pass true to set it as default, false if its just another token. This **does not** unset any other tokens that may be set as default. You can use `WC_Payment_Tokens::set_users_default()` to handle that instead.
``` php
$token = WC_Payment_Tokens::get( 42 ); // Token 42 is a default token for user 3
var_dump( $token->is_default() ); // returns true
$token->set_default( false );
var_dump( $token->is_default() ); // returns false
```
#### validate()
Does a check to make sure both the token and token type (CC, eCheck, ...) are present. See `WC_Payment_Token_CC::validate()` or `WC_Payment_Token_eCheck::validate()` for usage.
#### read( $token_id )
Load an existing token object from the database. See `WC_Payment_Tokens::get()` which is an alias of this function.
``` php
// Load a credit card toke, ID 55, user ID 5
$token = WC_Payment_Token_CC();
$token->read( 55 );
echo $token->get_id(); // returns 55
echo $token->get_user_id(); // returns 5
```
#### update()
Update an existing token. This will take any changed fields (`set_` functions) and actually save them to the database. Returns true or false depending on success.
``` php
$token = WC_Payment_Tokens::get( 42 ); // credit card token
$token->set_expiry_year( '2020' );
$token->set_expiry_month( '06 ');
$token->update();
```
#### create()
This will create a new token in the database. So once you build it, create() will create a new token in the database with the details. Returns true or false depending on success.
``` php
$token = new WC_Payment_Token_CC();
// set last4, expiry year, month, and card type
$token->create(); // save to database
```
#### save()
`save()` can be used in place of `update()` and `create()`. If you are working with an existing token, `save()` will call `update()`. A new token will call `create()`. Returns true or false depending on success.
``` php
// calls update
$token = WC_Payment_Tokens::get( 42 ); // credit card token
$token->set_expiry_year( '2020' );
$token->set_expiry_month( '06 ');
$token->save();
// calls create
$token = new WC_Payment_Token_CC();
// set last4, expiry year, month, and card type
$token->save();
```
#### delete()
Deletes a token from the database.
``` php
$token = WC_Payment_Tokens::get( 42 );
$token->delete();
```