Creating Payments

Learn how to send customer payment info directly to us.

🚧

PCI-DSS Warning

If you use this guide to process credit cards, we will likely ask you to submit proof of PCI-DSS compliance. You may be able to lessen the requirement by collecting token information client-side and using Tokens. Have a chat with your Customer Success representative for more details.

The simplest way around this is to integrate with Hosted Page or Hosted Fields.

In this guide we'll show you how to make payments directly through KOMOJU. By directly, we mean that your server sends payment details (e.g. a credit card number) to KOMOJU, and KOMOJU processes it immediately.

Some possible use cases for this style of integration might be:

  • You have a fully custom UI for collecting customer payment details, and want to use KOMOJU behind the scenes.
  • You have contracts with multiple payment service providers, including KOMOJU, and want to multiplex between them.

When using our API to create payments, you have 2 options. Either you can first create a Session and then "pay" for it, or you can just create a Payment directly. Usually the first method is the most versatile but we'll walk through both methods for completeness.

Method 1: Pay for a Session

This method of creating payments requires at least 2 API calls: one to create a Session object and one to create a Payment.

✅ Advantages❌ Disadvantages
Works with 3DS out of the box.Requires at least 2 API calls.
Can have multiple payment attempts for one order number.
Can send line items to KOMOJU for better fraud detection and bookkeeping.
Can supply shipping and billing address for improved fraud detection.
Can easily avoid PCI-DSS burden by calling "pay" on frontend.

This recipe shows a complete example. We'll go over the steps in detail here.

Step 1: create a session

Call the Session: Create API with the following attributes:

AuthenticationMethodEndpoint
Secret keyPOSThttps://komoju.com/api/v1/sessions
* = required
Request AttributeTypeDescription
amount *integerInteger amount of money. This is always in the lowest possible denomination for the given currency. For example, an amount of 1 could mean 1 yen, or 1 US cent.
currency *string3-letter currency identifier. Examples might be "USD" or "JPY.
return_urlstringURL to redirect the customer back to your website or app. Not strictly required, but highly recommended.
payment_data[external_order_num]stringYour system's order number. This must be unique per session.
payment_data[capture]enum"auto" or "manual". Defaults to "auto". Setting this to "manual" will initiate Two-Step Capture.
emailstringCustomer's email address. If this is present on the Session, payment_details[email] becomes optional.
namestringCustomer's name.
line_itemsarray of objectList of line items. See Session: Create for precise format.
metadataobjectKey-value pairs for your own internal use. For example, if you don't like our uniqueness validation on order number, you can put your order numbers in here. Any Payments created by this session will inherit its metadata.

The resulting Session object can be quite large. The attributes you'll care about depend on how you plan to use the session. In this case, we're just using the session as a carrier for payments, so these are the response attributes of interest:

Response AttributeTypeDescription
idstringUnique identifier for the Session. You'll need this for subsequent API calls.
payment_methodsarray of objectList of payment methods supported by the session.
payment_methods[i].typestringType slug corresponding to a payment type in Payment Details.

Step 2: pay for the session

Next, you'll want to call our Session: Pay endpoint.

AuthenticationMethodEndpoint
Secret or publishable keyPOSThttps://komoju.com/api/v1/sessions/{id}/pay
* = required
Request AttributeTypeDescription
payment_details *objectAn object representing the user input required for your specific payment method of choice. See Payment Details.
fraud_detailsobjectInformation about the customer's current browsing context. See Fraud Details.
captureenum"auto" or "manual", defaults to "auto". This overrides the value specified during Session creation.

Step 3: handle the pay result

The response from Session: Pay looks like this:

Response AttributeTypeDescription
statusenum"completed", "pending", or "error"
redirect_urlstringURL to redirect your customer to for next steps. More on this soon.
paymentobjectPayment object, same format as the response to Payment: Show. You can use this to access the response Payment Details object.

If status is not "error", then you can always handle this by redirecting your customer to redirect_url.

Here's a detailed breakdown of some different scenarios you might encounter here. When in doubt, just redirect to redirect_url.

statuscapturepayment.statusWhat this meansWhat you can do
"error"*N/ALikely invalid input, like a wrong credit card number.Ask the customer to try again.
You may call Session: Pay again on the same session.
"completed""auto""captured"Payment was successful.Redirect to redirect_url.
Alternatively, you may simply show "thanks for your order".
"completed""auto""authorized"Submission successful, awaiting customer action.Redirect to redirect_url. It will point to payment instructions.
Alternatively, manually show instructions (see Payment Details).
"completed""manual""authorized"Payment successfully authorized (Two-Step Capture)Redirect to redirect_url.
Alternatively, you may show "thanks for your order".
Later, you will want to call Payment: Capture on the resulting payment.
"pending"*"pending"User must log in to an external service to pay.Redirect to redirect_url. It will lead to either a payment app (e.g. PayPay), or a credit card 3D Secure login page. If credit card, you may render redirect_url in an iframe.

If you choose to not redirect to redirect_url in any of these cases, we recommend reading through the Payment Details doc to understand how your specific payment method(s) works.

Step 4: handle return URL and webhook

The return_url you specified when you created your session is where the customer will be sent when they finish submitting their payment information, or when they decide to cancel while on their payment app.

When the customer is redirected to return_url, a query parameter called session_id will be appended. Your back-end should use this session_id to call Session: Show, and check the Session's status.

Here's an example:

In addition to this return_url check, we recommend you set up Webhooks - specifically for payment.captured and payment.authorized. You can use the Payment's external_order_num, metadata, or session attributes to associate it with your order.


Method 2: Creating a Payment Directly

Here's how you can create payments without an associated Session.

✅ Advantages❌ Disadvantages
In some cases, can complete payment in only 1 API call. Might be simpler for your use-case.Skips 3DS by default for credit card. See 3D Secure Without a Session.
Order number must be unique per payment; awkward to represent multiple attempts for one order.
Requires special case code for each payment type. Harder to build a "one size fits all" integration that works with many payment methods.

Step 1: create payment

Call Payment: Create.

AuthenticationMethodEndpoint
Secret keyPOSThttps://komoju.com/api/v1/payments
* = required
Request AttributeTypeDescription
amount *integerInteger amount of money. This is always in the lowest possible denomination for the given currency. For example, an amount of 1 could mean 1 yen, or 1 US cent.
currency *string3-letter currency identifier. Examples might be "USD", or "JPY".
return_urlstringA URL for the customer to return to once they finish paying. This is optional for credit card payments.
capturebooleanSet to false if you want to perform Two-Step Capture.
taxintegerSet this to 0. The default is "auto" which is always 10% of your amount.
external_order_numstringYour system's order number. You can use this to associate KOMOJU payments with your own internal orders. This must be unique.
metadataobjectArbitrary key-value pairs for your internal use. For example, you can put your order number in here if our uniqueness validation on external_order_num causes problems.
payment_detailsobjectAn object containing payment method-specific attributes (see Payment Details).

See the Payment: Create reference for the full list. Most of the time, the attributes you see here are the only ones you'll need.

Step 2: handle the response

The Payment: Create endpoint returns a Payment object with the following attributes (non-exhaustive):

Response AttributeTypeDescription
idstringUnique Payment ID, used for performing further actions like Payment: Capture.
statusstringTells you whether or not the payment is paid. More on this soon.

Here's a breakdown of the different Payment status values you might encounter:

Payment statusMeaning
pendingPayment has been initiated but not confirmed. The response should have a payment_details.redirect_url. Send your customer to that URL, then listen for payment.captured webhooks.
authorizedTwo possible meanings, depending on the type of payment.

1. For long-form async payment methods (konbini, bank_transfer, payeasy), authorized payments are reserved but awaiting customer action (e.g. waiting for customer to go to the store and pay cash). This can take several days. You'll get a payment.captured webhook if/when the customer pays. Otherwise you will get a payment.expired webhook.

2. For all other payment methods, authorized refers to Two-Step Capture. This is where the funds are in your control, but haven't left the customer's account yet. These authorized payments are awaiting merchant action (e.g. merchant performs a manual capture when goods are shipped). You can call Payment: Capture to capture authorized funds, or Payment: Cancel to void the authorization.
capturedPayment was successful. The money will be transferred to your bank account next settlement.
refundedThe payment was completed, but has been fully refunded. Note that partially refunded payments remain captured. You'll never see this status in the response of Payment: Create.
cancelledEither the customer decided to cancel payment, or you called Payment: Cancel.
expiredPayment was pending or authorized with no action for too long.

How you handle this depends on your specific use case and which payment method you chose. Advice on handling specific payment methods can be found on the Payment Details page.

Note on handling Konbini / Convenience Store Payments

Konbini payments may have the following fields in the response:

  • instructions_url (All Konbini): This contains a URL to a page providing the required payment information as well as detailed instructions on how to perform the payment at the Konbini. It should be served to the end-user for their convenience.
  • receipt: This is a payment code that can be used for Konbini purchases.
    • For 7-Eleven, this is deprecated. This field should not be served to the end-user. The end user is required to access the URL served in the instructions_url field to perform payment at the store.
    • For others, this can be provided to end users along with confirmation_code, if available in the response. However, we strongly recommend providing just the URL from instructions_url to the end user, as it contains precise instructions as to how to perform payment at the store.
  • confirmation_code: This is available for some Konbini brands and can be used by end users to perform payment at the store, in combination with receipt. However, this is not recommended - like receipt, we recommend providing just the URL from instructions_url to the end-user, as it contains precise instructions as to how to perform payment.

Step 3: webhook

The definitive way to know when a payment has been captured is to listen for payment.captured Webhooks. We recommend putting your order processing logic into your webhook handler for payment.captured or payment.authorized.

Notes on return_url

For direct payments, when the customer redirects to your return_url, KOMOJU adds query parameters to the url. One such query parameter an HMAC that can be checked to verify that the redirect came from KOMOJU.

The HMAC is computed using the final part of the URL: the path and all the query params other than the HMAC itself, signed using your private key. So, for example if the return URL provided at payment creation is:

https://example.com/return

After a payment is completed, we will redirect to the following URL:

https://example.com/return?hmac=examplehmac&param1=a&param2=b

The message is the path + parameters with hmac removed, so in this case:

message = "/return?param1=a&param2=b"

Then you can calculate the HMAC using hmac-sha256 to verify that it matches our HMAC. Example Ruby code below:

OpenSSL::HMAC.hexdigest('sha256', your_private_key, message) => "examplehmac"


What’s Next