> Plus:
> This payment method is only available to be installed by Shopify Plus plans.
Custom credit card payments extensions allow Partners to specify the hosted fields necessary to process their custom credit cards. You can collect essential information, such as installment details and required card numbers, directly on the checkout page before payment. This streamlines the checkout process and enhances the buyer experience.
Custom credit card payments extensions are used primarily to help merchants accept their Private Label Credit Card (PLCC) on Shopify Checkout.
> Beta:
> Processing a payment with a custom credit card payments extension is currently in an invite-only closed beta.
## What you'll learn
> Note:
> This document builds upon the [credit card payments extension tutorial](/docs/apps/build/payments/credit-card/use-the-cli), which you may refer to as needed for additional guidance.
In this tutorial, you'll learn how to do the following tasks:
- Create a checkout UI extension
- Create a custom credit card payments extension
- Explore the payment, refund, void, reject and capture session flows, and how to implement them yourself
- Submit your payments extension for review
## Requirements
- Install [Shopify CLI](/docs/api/shopify-cli)
- Create a [Shopify Partner account](https://www.shopify.com/partners) and apply to [become a payments partner](/docs/apps/build/payments/payments-extension-review#payments-partner-application-review)
- Create a [development store](/docs/api/development-stores)
- Create an [encryption certificate](/docs/apps/build/payments/credit-card/manage-encryption-certificates)
> Note:
> All Partners must submit a valid Payment Card Industry (PCI) Attestation of Compliance (AOC) before access to custom credit card payment extension is granted.
## Step 1: Scaffold an app
To build a custom credit card payment extension you will need to create a new app, with a custom credit card payments extension and checkout UI extension correctly applied.
Create your new app using the [Shopify CLI](/docs/apps/build/scaffold-app). As a first step, we recommend deploying a skeleton app to establish a base for customization.
> Tip:
> To create payment extensions via Shopify CLI you must be using `v3.60.0` or above.
## Step 2: Create a checkout UI extension
After creating your app, generate a checkout UI extension and deploy your app to Shopify. This extension will be used to collect additional information that's required to process a payment.
1. Use the Shopify CLI to [scaffold](/docs/api/checkout-ui-extensions#scaffolding-extension) a checkout UI extension for your app.
2. Name your extension and choose to work in TypeScript React.
> Note:
A sample extension, written in Typescript React, is shown below in the [Sample Checkout UI Extension](/docs/apps/build/payments/credit-card/custom/use-the-cli#sample-checkout-ui-extension) section. Please make sure to use the extension target and APIs as shown in the example.
3. After you generate the extension, [deploy](/docs/api/shopify-cli/app/app-deploy) your app to [Shopify Partners](https://www.shopify.com/partners). This will allow you to link the checkout UI extension with your payments app extension in the next section.
4. Navigate to your app in Shopify Partners (Apps > Your App).
5. Click **Extensions**. At this point, you should see the checkout UI extension you created and released.
## Step 3: Create a payments extension
### Generate the extension
Your Shopify app becomes a payments app after you've created and configured your payments extension.
1. Run the following command to start generating your payment extension:
```bash?title: 'npm'
npm shopify app generate extension
```
```bash?title: 'yarn'
yarn shopify app generate extension
```
```bash?title: 'pnpm'
pnpm shopify app generate extension
```
1. When prompted, choose your organization & create this as a new app
1. When prompted for "Type of extension", select "Payments App Extension > Custom Credit Card" and name your extension
### Set up your payments extension
1. **Disable embedding**
Shopify apps are embedded by default, but payments apps are an exception to this, because they don't need to render anything in Shopify admin.
In `shopify.app.toml`, update the `embedded` and set it to false.
1. **Push the configuration changes to your app and start your server**
In a terminal, run the following commands to push the configuration changes to your app:
- Install the packages required to run the payments app:
```bash?title: 'npm'
npm install
```
```bash?title: 'yarn'
yarn
```
```bash?title: 'pnpm'
pnpm install
```
- Deploy your app to update the config, which is defined in `shopify.app.toml`:
```bash
shopify app deploy
```
1. Start your development server
To run the app locally, start your development server:
1. ```bash
shopify app dev
```
Required | The URL that receives payment and order details from the checkout. |
| `refund_session_url`
Required | The URL that refund session requests are sent to. |
| `capture_session_url`
Required | The URL that capture session requests are sent to.|
| `void_session_url`
Required | The URL that void session requests are sent to.|
| `confirmation_callback_url`
Optional | The URL that confirm session requests are sent to. This URL is required if your payments app supports 3-D Secure authentication. |
| `supported_countries`
Required | The countries where your payments app is available. Refer to the [list of ISO 3166 (alpha-2) country codes](https://www.iso.org/iso-3166-country-codes.html) where your app is available for installation by merchants. |
| `supports_3ds`
Required | 3-D Secure support is mandated in some instances. For example, you must enable the 3-D Secure field if you plan to support payments in countries which have mandated 3-D Secure. |
| `supported_payment_methods`
Required | The payment methods (for example, Visa) that are available with your payments app. [Learn more](https://github.com/activemerchant/payment_icons/blob/master/db/payment_icons.yml). |
| `supports_installments`
Required | Enables installments |
| `supports_deferred_payments`
Required | Enables deferred payments |
| `merchant_label`
Required | The name for your payment provider extension. This name is displayed to merchants in the Shopify admin when they search for payment methods to add to their store. Limited to 50 characters. |
| `buyer_label`
Optional | The name of the payment method. Your checkout name can be the same as your merchant admin name or it can be customized for customers. This name is displayed with the payment methods that you support in the customer checkout. After a checkout name has been set, translations should be provided for localization. |
| `test_mode_available`
Required | Enables merchants using your payments app to test their setup by simulating transactions. To test your app on a development store, your payment provider in the Shopify admin must be set to test mode. |
| `api_version`
Required | The Payments Apps GraphQL API version used by the payment provider app to receive requests from Shopify. You must use the same API version for sending GraphQL requests. You can't use the unstable version of the API in production. API versions are updated in accordance with Shopify's general [API versioning timelines](/docs/api/usage/versioning). |
| `multiple_capture`
Optional, Closed Beta | Enables merchants using your payment provider app to partially capture an authorized payment multiple times up to the full authorization amount. This is used only if your payments app supports merchant manual capture. |
| `encryption_certificate_fingerprint`
Required | The certificate that Shopify uses to generate the ephemeral key and encrypt the credit card information of the customer. Refer to [manage encryption certificates](/docs/apps/build/payments/credit-card/manage-encryption-certificates) section to learn more. |
| `ui_extension_handle`
Required | The UI extension that will be used to render your payments app in checkout. This value can only be a UI extension linked to this specific payments app.|
| `checkout_payment_method_fields`
Required | The fields your payments app will accept from buyers in checkout (for example, installment details, payment plan). Each field is composed of a key name, as well as the data type, that restricts the input the buyer can provider. |
| `checkout_hosted_fields`
Required | The hosted fields your payments app will accept from buyers in checkout (for example, cardholder name, expiration date). This should be an array of string. |
> Note:
> The `ui_extension_handle`, `checkout_payment_method_fields` and `checkout_hosted_fields` attributes are new app extension configurations. You’ll want to select the UI extension you created in **Create a Checkout UI Extension** as the value for the UI Extension field.
The UI extension generated in [Create a checkout UI extension](/docs/apps/build/payments/credit-card/custom/use-the-cli#step-2-create-a-checkout-ui-extension) will determine what fields, validation, and form submission behavior is presented to buyers during checkout.
### UI Extension
This is where you would identify the checkout extension you built prior to creating your payment app extension to tie them into one another.
| Property name | Description |
| ------------- | ---------------------------------------------------------------------------------- |
| `ui_extension_handle`
Required | The UI extension that will be used to render your payments app in checkout. This value can only be a UI extension linked to this specific payments app.|
### UI Extension Field Definitions
The fields you are looking to accept from your UI extensions so the payment method can validate the correct data is sent from the front end.
| Property name | Description |
| ------------- | ---------------------------------------------------------------------------------- |
| `checkout_payment_method_fields`
Required | The fields your payments app will accept from buyers in checkout (for example, installment details, payment plan). Each field is composed of a key name, as well as the data type, that restricts the input the buyer can provider. |
```
[[extensions.checkout_payment_method_fields]]
key = "bank_name"
type = "string"
required = true
[[extensions.checkout_payment_method_fields]]
key = "account_number"
type = "string"
required = false
```
The above field definitions would be defined for something that looks like this:

### Credit Card Fields
| Property name | Description |
| ------------- | ---------------------------------------------------------------------------------- |
| `checkout_hosted_fields`
Required | The hosted fields your payments app will accept from buyers in checkout (for example, cardholder name, expiration date). This should be an array of string. |
```
# Supported values: ["name", "expiry", "verification_value", "issue_date", "issue_number"]
checkout_hosted_fields = [ "name", "expiry", "verification_value" ]
```
The above field definitions would be defined for something that looks like this:

## Step 5: Submit your payments extension for review
After you've finished your draft, you can submit your payments extension for review. You can use this same process to submit new versions of your payments extension. Any changes that are made after publishing need to be approved by Shopify as a new version of the payments extension.
### Deploy your extension
To get your extension ready for review, you can create and release an app version with the `deploy` command.
1. Navigate to your app directory.
2. Run the following command.
```bash
shopify app deploy
```
An app version created using Shopify CLI contains the following:
- The app configuration from the local [configuration file](/docs/apps/build/cli-for-apps/app-configuration). If the `include_config_on_deploy` [flag](/docs/apps/build/cli-for-apps/app-configuration#build) is not set or `false`, the configuration from the active app version will be used instead.
- The local version of the app's CLI-managed extensions. If you have an extension in your deployed app, but the extension code doesn't exist locally, then the extension isn't included in your app version.
- The latest drafts of dashboard-managed extensions.
Releasing an app version replaces the current active version that's served to stores with your app installed. It might take several minutes for app users to be upgraded to the new version.
> Tip:
If you want to create a version, but want to avoid releasing it to users, then run the `deploy` command with a `--no-release` flag.
### Submit the app version for review
Payments apps are [reviewed by Shopify](/docs/apps/build/payments/payments-extension-review) to ensure that they provide great merchant experience. Follow these steps to submit your app version for review:
1. From the Partner Dashboard, go to **[Apps](https://partners.shopify.com/current/apps)**.
2. Select your app from the list.
3. Click **Versions**.
4. Select the version that you want to release.
5. Click **Submit for review**.
### Release your app version
After Shopify has reviewed and approved the app version you can release it to merchants.
1. From the Partner Dashboard, go to **[Apps](https://partners.shopify.com/current/apps)**.
2. Click **Release** to release the new app version to users.
> Tip:
You can release the unreleased app version using Shopify CLI's `release` command, or through the Partner Dashboard.
## Step 6: Test your payments app with a store
Once this version has been released, follow these steps to install your app on your development store:
1. From the app splash page, enter an account name.
2. Select **Ready** > **Unstable** and click **Submit**.
3. In the banner, click **Return to Shopify**.
5. Enable test mode.
5. Click **Activate**.
6. You can select `Resolve` to complete the payment, or `Reject` to cancel and go back.
## Explore the payment processing flows
The Payments App functions similarly to the Credit Card payment method, allowing you to gather additional information from the buyer at the outset to facilitate payment processing. The primary distinction is that checkout UI extension data is included in the `start_payment_session` body.
Outlined below is a comprehensive diagram depicting the potential flow for processing a custom credit card payment. It's important to note that the pending state is optional; you can directly proceed to either resolve or reject the payment if there is no need to place it in a pending state. For further details on processing credit card payments, please refer to this [resource](/docs/apps/build/payments/credit-card/use-the-cli).
Once we start the payment session with your payments app, that initiation will also contain the metadata in a shape similar to what was specified within the field definitions. A [sample payment session payload](/docs/apps/build/payments/credit-card/custom/use-the-cli#payment-session) of what is to be expected can be seen below.
### Payment session
Payments with payments apps are processed asynchronously. When the buyer completes their checkout, a request will be sent from Shopify to the *Payment session URL* defined in [Configure your payments app extension](/docs/apps/build/payments/credit-card/custom/use-the-cli#step-4-configure-your-payments-extension), with the checkout and payment details. The Payments app should respond with HTTP 2xx to indicate that the payment session was started, and should begin processing the custom credit card payment at this point.
The new metadata we are passing through payment session would be contained within the payment_method request params under attributes:
```json
"payment_method":{
"type":"credit_card"
"data":{
"attributes": [
{
"key": "payment_plan",
"value": "pay-in-full"
}
],
},
},
```