Test scenarios
Use this checklist to confirm that behavior matches this guide. Record items you cannot reproduce as unverified, not as successful.
Producing each status in the sandbox
There is no test operation that moves a payment to any status you choose. Produce the terminal statuses as follows.
canceled: The buyer cancels on STBLpay's My Page (マイページ). Cancellation is possible insigned, and inissue_pendingbefore the deposit is confirmed (Cancellation).expiredwithout signing: Wait untilcheckoutExpiresAt(the operation deadline) in the response. In the sandbox, this is 3 hours after creation.expiredafter the issuance reservation: Wait until the deposit deadline plus the grace period for confirmation (1 hour in the sandbox).merchantExpiresAtcan only be set more than 3 days after creation, so this takes several days (Deadlines).failedandnonce_conflict: There is no test operation that produces them on demand. Verify them with tests that mock STBLpay. Forfailed, reproduce the Webhook body and the status lookup response. Fornonce_conflict, no Webhook is sent, so reproduce only the status lookup response (their shapes are in the OpenAPI specification).
Creating a payment
- When you create a payment with
amountJpyas a string, the create response andcheckoutUrlare returned - When you pass the amount as a JSON number, or create a payment without
amountJpy, the request is rejected with 400common/invalid_request - When you resend the same
orderIdconsecutively or concurrently, the same payment is returned and no duplicate is created - When you create again with the same
orderIdas a payment that has expired, the existingexpiredpayment is returned, and you do not send the buyer tocheckoutUrlbut handle it bystatus - When you call with a nonexistent ID or invalid input, the error is returned in the form
{ code, details? }
Looking up the status
- When you call the status lookup API without an authentication header, only the fields of the status lookup response are returned, and the amount is not included
Moving to the checkout page
- When you do a top-level navigation to the
checkoutUrlin the create response, you reach the checkout page
How the status progresses
- When the buyer pays from their balance, the status goes from
signedtodeposit_confirmedwithout waiting for deposit detection - When the buyer pays with a deposit of JPYC issued through JPYC EX, the status goes from
issue_pendingtodeposit_confirmed - When only the missing amount is issued, the status goes to
deposit_confirmedif the current balance plus the issued amount is enough - For a payment that uses a wallet for the first time, the status goes through
deploying, returns todeposit_confirmed, and the payment is executed after that - When the operation deadline passes without a signature, the status goes from
createdtoexpired - After an issuance reservation, when the deposit is not complete by the deposit deadline (the issuance reservation deadline plus 14 days, or
merchantExpiresAtif you specified it and it is earlier) plus the confirmation-wait grace period, the status goes fromissue_pendingtoexpired - When a deposit arrives for a payment whose
canceledstatus is final, the payment is not revived and the funds remain in the buyer's wallet - When STBLpay cannot observe a cancellation at JPYC EX, it does not treat it as STBLpay's
canceled, and monitoring continues
Receiving Webhooks
- When a payment reaches a terminal state, you can handle each of
payment.settled,payment.failed,payment.canceled, andpayment.expired - When the transfer reaches a state where its outcome cannot be determined (
nonce_conflict), you can detect it with a status lookup without waiting for a Webhook, and ask the contact to investigate - When the raw body is tampered with, or the time exceeds the allowed range, the Webhook is not accepted
- When you send a test notification from the merchant console (
typeispayment.settledand the body hastest: true), you return2xxwithout changing any order. You checkteston the value right afterJSON.parseof the received body, not on a value after schema validation has dropped unknown keys - When two
v1values (old and new) are attached, verification works wherever the signature for the secret you currently hold is positioned - When you resend with only the event ID in the header changed, the body's
idprevents double processing - When the process stops just before saving the event, it does not return a success response, and recovers on resend
- When the process stops after saving the event and before updating the order, it can resume from the unprocessed event
- When a Webhook and a status lookup arrive at the same time, the order update, shipping, and notification run exactly once
- When an unknown event type arrives, it is ignored without changing the order
- When an unknown
failed_reasonvalue arrives, the Webhook is not rejected and is handled as a failure fallback
Checking on return
- When you tamper with the query of the browser's return destination, the order is not marked as paid
Refunds are available only through the Transaction details (取引の詳細) screen of the merchant console. To test a refund, prepare the owner's passkey approval and a balance in the receiving wallet.