### String to Sign Example Source: https://redotpay.readme.io/docs/redotpay-api-request-signature-and-verification-guide A concrete example of the string to sign using specific values. ```text POST /openapi/v2/order/create 4CA7B705-8EF5-4AC3-A0B6-9A4B84EF13B6.1763555087656.{"amount":100,"currency":"USD"} ``` -------------------------------- ### Complete Request Headers Example Source: https://redotpay.readme.io/docs/redotpay-api-request-signature-and-verification-guide An example of the final HTTP request headers including the signature. ```http POST /openapi/v2/order/create HTTP/1.1 Host: api.redotpay.com Content-Type: application/json X-Merchant-Ak: 4CA7B705-8EF5-4AC3-A0B6-9A4B84EF13B6 X-R-Ts: 1763555087656 X-R-Key-Version: 1 X-R-Signature: URL-encoded Base64 signature string {"amount":100,"currency":"USD"} ``` -------------------------------- ### Include API Request Headers Source: https://redotpay.readme.io/docs/getting-started Example of a POST request including all mandatory authentication and signature headers. ```http POST /openapi/v2/order/create HTTP/1.1 Host: api-sandbox.redotpay.com Content-Type: application/json X-R-AK: 4CA7B705-8EF5-4AC3-A0B6-9A4B84EF13B6 X-R-TS: 1763555087656 X-R-KEY-VERSION: 1 X-R-Signature: ZxAmLpVyzQEGBE5fC6bqLq7KjRzP5HdVoT4nLkP8x7c=... (full signature) { "orderId": "TEST_ORDER_001", "amount": "88.88", "currency": "USD" } ``` -------------------------------- ### API Response Examples Source: https://redotpay.readme.io/docs/getting-started JSON structures for successful and error responses from the API. ```json { "code": "SUCCESS", "msg": null, "data": { "orderSn": "P20250125123000123456", "outerOrder": "TEST_ORDER_001", "h5Url": "https://pay.redotpay.com/checkout/..." } } ``` ```json { "code": "signError", "msg": "sign verify failed", "data": null } ``` -------------------------------- ### Refund Webhook Request Example Source: https://redotpay.readme.io/docs/webhook Example JSON payload sent by the server to the merchant's webhook endpoint upon a refund event. ```json { "refundSn": "RE2025121402253023...", "merchantRefundSn": "TestRefund20251201...", "merchantId": 2135213432..., "status": "SUCCESS", "completeTime": 1768357531591, "outerOrderSn": "test-quick-pay-1768301309...", "refundType": "redotpay", "createTime": 1768354530000, "refundAmount": 0.01001, "refundCurrency": "USDT", "eventType": "MERCHANT" } ``` -------------------------------- ### Webhook Response Examples Source: https://redotpay.readme.io/docs/webhook JSON response formats for successful and failed webhook processing. ```json { "code": "SUCCESS", "requestId": "0195c081-d54e-4569-a657-0f54388fa9ba" } ``` ```json { "code": "FAIL", "requestId": "0d992439-38a7-4674-9e06-19a7602eae2e", "msg":"update failed" } ``` -------------------------------- ### Payment Webhook Request Payload Source: https://redotpay.readme.io/docs/webhook Example JSON structure for a payment webhook notification. Use this to parse incoming POST requests from the payment gateway. ```json { "outerOrder": "T300088...", "preSn": "RAP202601051045558385...", "orderCurrency": "USD", "billCoin": "USD", "outerUid": "T3111...", "txId": "PAYH20260105104613401...", "rateExtra": 0, "actionType": "ACQUIRER_PAY", "billAmount": 0.99, "orderAmount": 1, "orderTime": 1767609970940, "merchantId": 3000000..., "cryptoAmount": 1, "rate": 1, "walletName": "redotpay", "paymentDeadline": 1767611755616, "sn": "RA20260105104610940923...", "paymentTime": 1767609973423, "orderStatus": 2, "coin": "USDT", "clientIp": "13.230.109.247", "source": "WEB" } ``` -------------------------------- ### POST /openapi/v2/refund/create Source: https://redotpay.readme.io/reference/createrefund-1 Initiate a refund for a previously created order. Returns the acquirer refund identifier and the initial refund status. ```APIDOC ## POST https://acquirersandbox.rp-2023app.com/openapi/v2/refund/create ### Description Initiate a refund for a previously created order. Returns the acquirer refund identifier and the initial refund status (e.g. REFUNDING). Use this API to submit merchant-initiated refunds. ### Method POST ### Endpoint https://acquirersandbox.rp-2023app.com/openapi/v2/refund/create ### Parameters #### Request Body - **merchantRefundSn** (string) - Required - Merchant's external refund identifier. Max length: 64 characters. Allowed characters: letters, numbers and _ - | * @ - **outerOrderSn** (string) - Required - Merchant's original order identifier. - **reason** (string) - Required - Refund reason provided by the merchant. - **refundAmount** (number) - Optional - Used for partial refund of order. If not specified, it defaults to a full refund. #### Headers - **X-R-Ts** (string) - Required - request timestamp in milliseconds - **X-R-Ak** (string) - Required - merchant's appKey - **X-R-Signature** (string) - Required - request signature - **X-R-Key-Version** (string) - Optional - merchant's private key version, default is 1 - **accept** (string) - Optional - Defaults to application/json ### Response #### Success Response (200) - OK #### Error Responses - 400: request param invalid or format error - 401: JWT has expired or JWT is illegal - 403: request ip not in the white list - 429: exceed api frequest frequency limit ``` -------------------------------- ### POST /openapi/v2/order/create Source: https://redotpay.readme.io/docs/getting-started Creates a new order in the RedotPay system. This endpoint requires specific authentication headers including X-R-AK, X-R-TS, X-R-KEY-VERSION, and X-R-Signature. ```APIDOC ## POST /openapi/v2/order/create ### Description Creates a new order for payment processing. ### Method POST ### Endpoint /openapi/v2/order/create ### Request Body - **orderId** (string) - Required - Unique identifier for the order in the merchant system. - **amount** (string) - Required - The transaction amount. - **currency** (string) - Required - The currency code (e.g., USD). ### Request Example { "orderId": "TEST_ORDER_001", "amount": "88.88", "currency": "USD" } ### Response #### Success Response (200) - **code** (string) - Status code indicating success. - **data** (object) - Contains order details including orderSn and h5Url. #### Response Example { "code": "SUCCESS", "msg": null, "data": { "orderSn": "P20250125123000123456", "outerOrder": "TEST_ORDER_001", "h5Url": "https://pay.redotpay.com/checkout/..." } } ``` -------------------------------- ### POST /openapi/v2/order/create Source: https://redotpay.readme.io/reference/createprepayorder-1 Creates a payment order and returns checkout URLs or deep links for supported channels (WEB, H5, APP). ```APIDOC ## POST /openapi/v2/order/create ### Description Create a payment order and return checkout URLs / deep links for supported channels (WEB, H5, APP). The response contains redirect URLs and the list of available payment methods. Redirect the payer to the returned URL to complete the transaction. ### Method POST ### Endpoint https://acquirersandbox.rp-2023app.com/openapi/v2/order/create ### Parameters #### Request Body - **outerOrder** (string) - Optional - Merchant's external order identifier. - **outerOrderSn** (string) - Required - Merchant's external order identifier. - **outerUid** (string) - Required - Merchant's external user id. - **orderAmount** (number) - Required - Order total amount in fiat. - **orderCurrency** (string) - Required - Order fiat currency, compliant with ISO 4217. - **timeExpire** (int64) - Optional - Payment expire time in milliseconds. - **env** (string) - Required - Payment environment (H5, WEB, APP). - **rateExtra** (number) - Optional - Merchant exchange rate markup. - **orderDesc** (string) - Required - Order description. - **goods** (array of objects) - Required - Product list. - **buyer** (object) - Optional - Payment buyer information. - **redirectUrl** (string) - Optional - The URL to redirect to after a payment via web version. - **deeplink** (string) - Optional - The URL to redirect to after a payment via APP/H5. - **merchantName** (string) - Optional - The name of the receiving merchant. ### Response #### Success Response (200) - **OK** - Transaction successfully initiated. #### Error Responses - **400** - Request param invalid or format error - **401** - JWT has expired or JWT is illegal - **403** - Request ip not in the white list - **429** - Exceed api frequency limit ``` -------------------------------- ### Create payment order request Source: https://redotpay.readme.io/reference/createprepayorder-1 This endpoint requires specific headers for authentication and a JSON body containing order, buyer, and product information. ```Shell curl --request POST \ --url https://acquirersandbox.rp-2023app.com/openapi/v2/order/create \ --header 'Content-Type: application/json' \ --header 'X-R-Ak: ' \ --header 'X-R-Signature: ' \ --header 'X-R-Ts: ' \ --data '{ "outerOrderSn": "ORDER123456", "outerUid": "USER789", "orderAmount": 100.00, "orderCurrency": "USD", "env": "WEB", "orderDesc": "Purchase of goods", "goods": [ { "goodsType": "01", "goodsCategory": "0000", "goodsCode": "PROD001", "goodsName": "Sample Product", "goodsCount": 1, "goodsAmount": 100.00, "goodsCoin": "USD" } ] }' ``` -------------------------------- ### API Environments Source: https://redotpay.readme.io/docs/getting-started RedotPay provides separate environments for testing and production. ```APIDOC ## API Environments ### Description RedotPay Connect provides two environments for API interaction. ### Environments - **Sandbox**: https://acquirersandbox.rp-2023app.com/{endpoint} - Used for functional testing and integration. - **Production**: https://acquirer.redotpay.com/{endpoint} - Used for live transaction processing. ``` -------------------------------- ### Generate RSA Key Pair with OpenSSL Source: https://redotpay.readme.io/docs/redotpay-api-request-signature-and-verification-guide Use these commands to create a 2048-bit RSA private key and extract the corresponding public key. ```bash # Generate private key openssl genrsa -out private_key.pem 2048 # Generate public key from private key openssl rsa -in private_key.pem -pubout -out public_key.pem ``` -------------------------------- ### String to Sign Format Source: https://redotpay.readme.io/docs/redotpay-api-request-signature-and-verification-guide The required format for the string to be signed, including HTTP method, URI, app key, timestamp, and request body. ```text {http-method} {http-uri} {appKey}.{timestamp}.{requestBody} ``` -------------------------------- ### Initiate merchant refund request Source: https://redotpay.readme.io/reference/createrefund-1 The endpoint requires specific headers for authentication and request validation, including a timestamp, appKey, and signature. ```Shell curl --request POST \ --url https://acquirersandbox.rp-2023app.com/openapi/v2/refund/create \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --header 'X-R-Ak: ' \ --header 'X-R-Signature: ' \ --header 'X-R-Ts: ' \ --data '{ "merchantRefundSn": "string", "outerOrderSn": "string", "reason": "string", "refundAmount": 0 }' ``` -------------------------------- ### Batch query payment orders via cURL Source: https://redotpay.readme.io/reference/paymentorder-1 Use this cURL command to query payment orders. Ensure the required headers like X-R-Ts, X-R-Ak, and X-R-Signature are included in your actual implementation. ```Shell curl --request POST \ --url https://acquirersandbox.rp-2023app.com/openapi/v2/order/list \ --header 'accept: application/json' \ --header 'content-type: application/json' ``` -------------------------------- ### RSA Signature Generation in Java Source: https://redotpay.readme.io/docs/redotpay-api-request-signature-and-verification-guide Implementation for generating an RSA signature and loading a private key in Java. ```java import java.security.*; import java.util.Base64; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; public class RsaSignatureGenerator { public static String generateSignature(String httpMethod, String httpUri, String appKey, PrivateKey privateKey, long timestamp, String requestBody) throws Exception { // 1. Construct the string to sign String stringToSign = String.format("%s %s\n%s.%d.%s", httpMethod, httpUri, appKey, timestamp, requestBody); // 2. Sign using SHA256withRSA Signature privateSignature = Signature.getInstance("SHA256withRSA"); privateSignature.initSign(privateKey); privateSignature.update(stringToSign.getBytes(StandardCharsets.UTF_8)); byte[] signatureBytes = privateSignature.sign(); // 3. Base64 encode and URL encode String base64Signature = Base64.getEncoder().encodeToString(signatureBytes); return base64Signature; } // Load private key public static PrivateKey loadPrivateKey(String keyPath) throws Exception { String privateKeyPEM = new String(java.nio.file.Files.readAllBytes( java.nio.file.Paths.get(keyPath))); privateKeyPEM = privateKeyPEM .replace("-----BEGIN PRIVATE KEY-----", "") .replace("-----END PRIVATE KEY-----", "") .replaceAll("\\s", ""); byte[] decoded = Base64.getDecoder().decode(privateKeyPEM); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(decoded)); } } ``` -------------------------------- ### POST /openapi/v2/order/detail Source: https://redotpay.readme.io/reference/paymentorderdetail-1 Query the current status and full details of a payment order by preSn or outerOrder. Response includes fiat and crypto amounts, exchange rate, channel/wallet identifiers, transaction IDs and relevant timestamps. ```APIDOC ## POST /openapi/v2/order/detail ### Description Query the current status and full details of a payment order by preSn or outerOrder. Response includes fiat and crypto amounts, exchange rate, channel/wallet identifiers, transaction IDs and relevant timestamps. ### Method POST ### Endpoint https://acquirersandbox.rp-2023app.com/openapi/v2/order/detail ### Parameters #### Headers - **X-R-Ts** (string) - Required - request timestamp in milliseconds - **X-R-Ak** (string) - Required - merchant's appKey - **X-R-Signature** (string) - Required - request signature - **X-R-Key-Version** (string) - Optional - merchant's private key version, default is 1 - **accept** (string) - Optional - Defaults to application/json #### Request Body - **outerOrderSn** (string) - Optional - merchant's outer order - **orderSn** (string) - Optional - payment serial number ### Response #### Success Response (200) - OK #### Error Responses - 400: request param invalid or format error - 401: JWT has expired or JWT is illegal - 403: request ip not in the white list - 429: exceed api frequest frequency limit ``` -------------------------------- ### POST /openapi/v2/merchant/asset/query Source: https://redotpay.readme.io/reference/accountasset Retrieve merchant account balances and asset summary information, including total, available and frozen balances. ```APIDOC ## POST /openapi/v2/merchant/asset/query ### Description Retrieve merchant account balances and asset summary information, including total, available and frozen balances (reported in merchant base currency, typically USD). ### Method POST ### Endpoint https://acquirersandbox.rp-2023app.com/openapi/v2/merchant/asset/query ### Parameters #### Headers - **X-R-Ts** (string) - Required - request timestamp in milliseconds - **X-R-Ak** (string) - Required - merchant's appKey - **X-R-Signature** (string) - Required - request signature - **X-R-Key-Version** (string) - Optional - merchant's private key version, default is 1 - **accept** (string) - Optional - Defaults to application/json ### Response #### Success Response (200) - OK #### Error Responses - 400: request param invalid or format error - 401: JWT has expired or JWT is illegal - 403: request ip not in the white list - 429: exceed api frequest frequency limit ``` -------------------------------- ### POST /openapi/v2/order/list Source: https://redotpay.readme.io/reference/paymentorder-1 Batch query payment orders by merchant outer order numbers or by time range. ```APIDOC ## POST /openapi/v2/order/list ### Description Batch query payment orders by merchant outer order numbers or by time range. If outerOrderList is provided, beginTime/endTime are ignored. Time-based queries are limited to recent history (up to 30 days). ### Method POST ### Endpoint https://acquirersandbox.rp-2023app.com/openapi/v2/order/list ### Parameters #### Request Body - **outerOrderSnList** (array of strings) - Optional - A list of merchant outer order numbers to filter the query by. - **beginTime** (int64) - Optional - The start time of the query range in milliseconds. Required if outerOrderList is not provided. - **endTime** (int64) - Optional - The end time of the query range in milliseconds. Required if outerOrderList is not provided. - **pageNo** (int32) - Optional - The page number for pagination (1 to 10000). Default: 1. - **pageSize** (int32) - Optional - The number of items per page to retrieve (10 to 1000). Default: 10. #### Headers - **X-R-Ts** (string) - Required - Request timestamp in milliseconds. - **X-R-Ak** (string) - Required - Merchant's appKey. - **X-R-Signature** (string) - Required - Request signature. - **X-R-Key-Version** (string) - Optional - Merchant's private key version, default is 1. - **accept** (string) - Optional - Defaults to application/json. ### Response #### Success Response (200) - OK #### Error Responses - 400: request param invalid or format error - 401: JWT has expired or JWT is illegal - 403: request ip not in the white list - 429: exceed api frequest frequency limit ``` -------------------------------- ### Query payment order status via cURL Source: https://redotpay.readme.io/reference/paymentorderdetail-1 Use this cURL request to retrieve order details from the sandbox environment. ```Shell curl --request POST \ --url https://acquirersandbox.rp-2023app.com/openapi/v2/order/detail \ --header 'accept: application/json' \ --header 'content-type: application/json' ``` -------------------------------- ### Create Order API Request Source: https://redotpay.readme.io/docs/getting-started Standard HTTP POST request for creating an order. Requires specific headers including X-R-AK, X-R-TS, and X-R-Signature. ```http POST /openapi/v2/order/create HTTP/1.1 Host: api-sandbox.redotpay.com Content-Type: application/json X-R-AK: 4CA7B705-8EF5-4AC3-A0B6-9A4B84EF13B6 X-R-TS: 1763555087656 X-R-KEY-VERSION: 1 X-R-Signature: 5415c7bcc8c93e5f... (example, actual is longer) { "orderId": "TEST_ORDER_001", "amount": "88.88", "currency": "USD" } ``` -------------------------------- ### List merchant asset transaction logs request Source: https://redotpay.readme.io/reference/assetloglist-1 The endpoint requires mandatory body parameters for time range and pagination, along with authentication headers. ```Shell curl -X POST https://acquirersandbox.rp-2023app.com/openapi/v2/merchant/asset/log/list \ -H "X-R-Ts: " \ -H "X-R-Ak: " \ -H "X-R-Signature: " \ -H "Content-Type: application/json" \ -d '{ "createTimeStart": 1672531200000, "createTimeEnd": 1673136000000, "pageNo": 1, "pageSize": 10 }' ``` -------------------------------- ### Verify RedotPay Callback Signature in Python Source: https://redotpay.readme.io/docs/redotpay-api-request-signature-and-verification-guide Uses the cryptography library to verify the signature of a callback request. Requires the public key corresponding to the received key version. ```python import base64 import urllib.parse from cryptography.hazmat.primitives import serialization, hashes from cryptography.hazmat.primitives.asymmetric import padding from cryptography.exceptions import InvalidSignature from cryptography.hazmat.backends import default_backend def verify_callback_signature(headers: dict, request_body: str, app_key: str, expected_key_version: int) -> bool: """ Verify callback signature :param headers: Request headers containing X-R-Ts, X-R-Signature, X-R-Key-Version :param request_body: Original request body :param app_key: Merchant appKey :param expected_key_version: Expected key version (natural number) :return: Verification result """ try: # 1. Extract parameters from headers timestamp = headers.get('X-R-Ts') encoded_signature = headers.get('X-R-Signature') received_key_version = headers.get('X-R-Key-Version') # 2. Check key version if not received_key_version or int(received_key_version) != expected_key_version: return False # 3. Get corresponding RedotPay public key public_key = get_redotpay_public_key(int(received_key_version)) # 4. Decode signature decoded_signature = urllib.parse.unquote(encoded_signature) signature_bytes = base64.b64decode(decoded_signature) # 5. Construct verification string string_to_verify = f"{app_key}.{timestamp}.{request_body}" # 6. Verify signature public_key.verify( signature_bytes, string_to_verify.encode('utf-8'), padding.PKCS1v15(), hashes.SHA256() ) return True except (InvalidSignature, ValueError, KeyError, TypeError): return False def get_redotpay_public_key(key_version: int): """ Get RedotPay public key based on key version :param key_version: Key version (natural number) """ # Get corresponding public key file path based on version number key_file_path = f"redotpay_public_key_v{key_version}.pem" with open(key_file_path, "rb") as key_file: return serialization.load_pem_public_key( key_file.read(), backend=default_backend() ) ``` -------------------------------- ### POST /openapi/v2/merchant/asset/log/list Source: https://redotpay.readme.io/reference/assetloglist-1 Retrieve paginated ledger entries (asset transaction logs) for a merchant within the requested time window. ```APIDOC ## POST https://acquirersandbox.rp-2023app.com/openapi/v2/merchant/asset/log/list ### Description Retrieve paginated ledger entries (asset transaction logs) for a merchant within the requested time window. Supports pagination and filtering by time range and transaction type. ### Method POST ### Endpoint https://acquirersandbox.rp-2023app.com/openapi/v2/merchant/asset/log/list ### Parameters #### Headers - **X-R-Ts** (string) - Required - request timestamp in milliseconds - **X-R-Ak** (string) - Required - merchant's appKey - **X-R-Signature** (string) - Required - request signature - **X-R-Key-Version** (string) - Optional - merchant's private key version, default is 1 - **accept** (string) - Optional - Defaults to application/json #### Request Body - **createTimeStart** (int64) - Required - asset change log start time, supports up to six-months gap - **createTimeEnd** (int64) - Required - asset change log end time, supports up to six-months gap - **pageNo** (int32) - Required - query page no, minimum is 1 - **pageSize** (int32) - Required - query page size, max is 500 ### Response #### Success Response (200) - OK #### Error Responses - 400: request param invalid or format error - 401: JWT has expired or JWT is illegal - 403: request ip not in the white list - 429: exceed api frequest frequency limit ``` -------------------------------- ### Fetch payment method details via cURL Source: https://redotpay.readme.io/reference/paymentmethod Use this cURL request to retrieve payment method details. Ensure the required headers and body parameters are included in your request. ```Shell curl --request POST \ --url https://acquirersandbox.rp-2023app.com/openapi/v2/order/payment-method \ --header 'accept: application/json' \ --header 'content-type: application/json' ``` -------------------------------- ### Java Callback Verification Source: https://redotpay.readme.io/docs/redotpay-api-request-signature-and-verification-guide Implementation for verifying RSA signatures in Java using SHA256withRSA. ```java import java.security.*; import java.util.Base64; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; public class CallbackVerifier { public static boolean verifyCallback(String appKey, String timestamp, String requestBody, String encodedSignature, int keyVersion, PublicKey redotpayPublicKey) throws Exception { // 1. Decode signature String decodedSignature = URLDecoder.decode(encodedSignature, StandardCharsets.UTF_8.toString()); byte[] signatureBytes = Base64.getDecoder().decode(decodedSignature); // 2. Construct verification string String stringToVerify = String.format("%s.%s.%s", appKey, timestamp, requestBody); // 3. Verify signature Signature publicSignature = Signature.getInstance("SHA256withRSA"); publicSignature.initVerify(redotpayPublicKey); publicSignature.update(stringToVerify.getBytes(StandardCharsets.UTF_8)); return publicSignature.verify(signatureBytes); } // Load RedotPay public key public static PublicKey loadRedotpayPublicKey(int keyVersion) throws Exception { // Get corresponding RedotPay public key based on keyVersion // This should obtain the public key string from secure storage or configuration String publicKeyPEM = getPublicKeyByVersion(keyVersion); publicKeyPEM = publicKeyPEM .replace("-----BEGIN PUBLIC KEY-----", "") .replace("-----END PUBLIC KEY-----", "") .replaceAll("\\s", ""); byte[] decoded = Base64.getDecoder().decode(publicKeyPEM); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePublic(new X509EncodedKeySpec(decoded)); } // Get public key by version private static String getPublicKeyByVersion(int version) { switch (version) { case 1: return "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."; // Version 1 public key case 2: return "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."; // Version 2 public key default: throw new IllegalArgumentException("Unsupported key version: " + version); } } } ``` -------------------------------- ### Query merchant account balances via cURL Source: https://redotpay.readme.io/reference/accountasset Use this cURL request to retrieve merchant account balances and asset summary information. ```Shell curl --request POST \ --url https://acquirersandbox.rp-2023app.com/openapi/v2/merchant/asset/query \ --header 'accept: application/json' ``` -------------------------------- ### Handle Signature Exceptions in Java Source: https://redotpay.readme.io/docs/redotpay-api-request-signature-and-verification-guide Catch specific exceptions during signature or verification processes to identify issues like invalid keys, algorithm parameters, or format errors. ```java try { // Signature or verification logic } catch (InvalidKeyException e) { // Invalid key, check key format or version } catch (SignatureException e) { // Signature verification failed } catch (InvalidAlgorithmParameterException e) { // Algorithm parameter error } catch (NumberFormatException e) { // Key version number format error, cannot convert to natural number } ``` -------------------------------- ### Callback Notification Signature Format Source: https://redotpay.readme.io/docs/redotpay-api-request-signature-and-verification-guide The format used to construct the string for signature verification. ```text {appKey}.{timestamp}.{requestBody} ``` -------------------------------- ### Close Payment Order Request Source: https://redotpay.readme.io/reference/closeorder This endpoint requires authentication headers including a timestamp, appKey, and request signature. ```Shell Loading… ``` -------------------------------- ### RSA Signature Generation in Python Source: https://redotpay.readme.io/docs/redotpay-api-request-signature-and-verification-guide Implementation for generating an RSA signature using the cryptography library in Python. ```python import base64 import urllib.parse from cryptography.hazmat.primitives import serialization, hashes from cryptography.hazmat.primitives.asymmetric import padding from cryptography.hazmat.backends import default_backend import time def generate_signature(http_method: str, http_uri: str, app_key: str, private_key_path: str, request_body: str) -> tuple: """ Generate RSA signature :return: (timestamp, signature, key_version) tuple """ # 1. Get timestamp and key version timestamp = int(time.time() * 1000) key_version = 1 # Adjust according to the actual key version used # 2. Construct the string to sign string_to_sign = f"{http_method} {http_uri}\n{app_key}.{timestamp}.{request_body}" # 3. Load private key with open(private_key_path, "rb") as key_file: private_key = serialization.load_pem_private_key( key_file.read(), password=None, backend=default_backend() ) # 4. Sign using SHA256 signature_bytes = private_key.sign( string_to_sign.encode('utf-8'), padding.PKCS1v15(), hashes.SHA256() ) # 5. Base64 encode and URL encode return base64.b64encode(signature_bytes).decode('utf-8') ``` -------------------------------- ### Signature Generation Formula Source: https://redotpay.readme.io/docs/redotpay-api-request-signature-and-verification-guide The mathematical formula for generating the request signature. ```text signature = base64Encode(sha256withRSA(stringToSign, privateKey)) ``` -------------------------------- ### POST /openapi/v2/order/payment-method Source: https://redotpay.readme.io/reference/paymentmethod Retrieve channel-specific details for a given payment method linked to a payment order. At least one of 'orderSn' or 'outerOrderSn' must be provided in the request body. ```APIDOC ## POST /openapi/v2/order/payment-method ### Description Retrieve channel-specific details for a given payment method linked to a payment order, including payment URLs, QR codes, deep links and method metadata required to render the checkout experience. ### Method POST ### Endpoint https://acquirersandbox.rp-2023app.com/openapi/v2/order/payment-method ### Parameters #### Headers - **X-R-Ts** (string) - Required - request timestamp in milliseconds - **X-R-Ak** (string) - Required - merchant's appKey - **X-R-Signature** (string) - Required - request signature - **X-R-Key-Version** (string) - Optional - merchant's private key version, default is 1 - **accept** (string) - Optional - Defaults to application/json #### Request Body - **methodId** (string) - Required - payment order's method id - **orderSn** (string) - Required - payment order's serial number - **outerOrderSn** (string) - Optional - merchant's outer order serial number ### Response #### Success Response (200) - **OK** #### Error Responses - **400** - request param invalid or format error - **401** - JWT has expired or JWT is illegal - **403** - request ip not in the white list - **429** - exceed api frequest frequency limit ``` -------------------------------- ### POST /openapi/v2/refund/detail Source: https://redotpay.readme.io/reference/refunddetail-1 Retrieve refund transaction details by either the acquirer-assigned refund ID (refundSn) or the merchant's refund reference (merchantRefundSn). ```APIDOC ## POST https://acquirersandbox.rp-2023app.com/openapi/v2/refund/detail ### Description Retrieve refund transaction details by either the acquirer-assigned refund ID (refundSn) or the merchant's refund reference (merchantRefundSn). Response includes refund status, refunded amount, currency, timestamps and related settlement metadata. ### Method POST ### Endpoint https://acquirersandbox.rp-2023app.com/openapi/v2/refund/detail ### Parameters #### Request Body - **refundSn** (string) - Optional - Acquirer-assigned refund identifier - **merchantRefundSn** (string) - Required - Merchant's reference for the refund (outer refund ID) #### Headers - **X-R-Ts** (string) - Required - request timestamp in milliseconds - **X-R-Ak** (string) - Required - merchant's appKey - **X-R-Signature** (string) - Required - request signature - **X-R-Key-Version** (string) - Optional - merchant's private key version, default is 1 - **accept** (string) - Optional - Defaults to application/json ### Response #### Success Response (200) - **OK** - Request successful #### Error Responses - **400** - request param invalid or format error - **401** - JWT has expired or JWT is illegal - **403** - request ip not in the white list - **429** - exceed api frequest frequency limit ``` -------------------------------- ### API Authentication Headers Source: https://redotpay.readme.io/docs/getting-started All RedotPay API requests require specific headers for authentication and security validation. ```APIDOC ## API Authentication Headers ### Description All API requests must include specific HTTP headers for authentication, security, and signature validation. ### Headers - **X-R-AK** (String) - Required - Merchant appKey for account identification. - **X-R-TS** (Number) - Required - Timestamp in milliseconds for replay attack prevention. - **X-R-KEY-VERSION** (Number) - Required - Version of the key pair used for the signature. - **X-R-Signature** (String) - Required - Base64-encoded SHA256withRSA digital signature. - **Content-Type** (String) - Required - Must be 'application/json'. ``` -------------------------------- ### POST /openapi/v2/order/close Source: https://redotpay.readme.io/reference/closeorder Closes all pending orders under a specific payment order. If the payment has already been made, the request will fail. ```APIDOC ## POST /openapi/v2/order/close ### Description Close all pending orders under this payment order. If payment has already been made, the closure will fail. ### Method POST ### Endpoint https://acquirersandbox.rp-2023app.com/openapi/v2/order/close ### Parameters #### Request Body - **orderSn** (string) - Required - payment order's serial number #### Headers - **X-R-Ts** (string) - Required - request timestamp in milliseconds - **X-R-Ak** (string) - Required - merchant's appKey - **X-R-Signature** (string) - Required - request signature - **X-R-Key-Version** (string) - Optional - merchant's private key version, default is 1 - **accept** (string) - Optional - Defaults to application/json ### Response #### Success Response (200) - OK #### Error Responses - 400: request param invalid or format error - 401: JWT has expired or JWT is illegal - 403: request ip not in the white list - 429: exceed api frequest frequency limit ``` -------------------------------- ### Retrieve refund details via cURL Source: https://redotpay.readme.io/reference/refunddetail-1 Use this cURL request to query refund transaction details. Ensure the required headers like X-R-Ts, X-R-Ak, and X-R-Signature are included in your request. ```Shell curl --request POST \ --url https://acquirersandbox.rp-2023app.com/openapi/v2/refund/detail \ --header 'accept: application/json' \ --header 'content-type: application/json' ``` -------------------------------- ### Webhook Response Specification Source: https://redotpay.readme.io/docs/webhook Defines the required JSON response structure that the merchant's system must return after processing a webhook notification. ```APIDOC ## Webhook Response ### Description After your system processes the webhook, your endpoint should return a JSON response to acknowledge receipt. The system will retry the request if a non-SUCCESS code is returned. ### Response Fields - **code** (String) - Required - "SUCCESS" or "FAIL" - **msg** (String) - Optional - Error message, present only when code is "FAIL" - **requestId** (String) - Required - Unique request ID ### Response Examples #### Success Response (200) { "code": "SUCCESS", "requestId": "0195c081-d54e-4569-a657-0f54388fa9ba" } #### Fail Response (200) { "code": "FAIL", "requestId": "0d992439-38a7-4674-9e06-19a7602eae2e", "msg": "update failed" } ### Retry Policy - **Condition**: Non-SUCCESS code response - **Retry Interval**: 180 seconds - **Max Retries**: 3 ``` -------------------------------- ### Refund Webhook Event Source: https://redotpay.readme.io/docs/webhook The Refund Webhook notifies the merchant about the status of a refund request. It includes details such as the refund serial number, status, and associated order information. ```APIDOC ## Refund Webhook ### Description This webhook event is triggered to notify the merchant of updates regarding a refund request, including status changes and completion details. ### Parameters - **merchantRefundSn** (String) - Required - Refund serial number sent by the merchant when initiating the refund - **refundSn** (String) - Required - Refund reference number - **status** (String) - Required - Refund result status: REFUNDING, SUCCESS, FAILED - **failRason** (String) - Optional - Explains why refund order fails - **merchantId** (int) - Required - Merchant's unique ID - **failReason** (String) - Optional - Reason the refund failed - **completeTime** (long) - Required - Refund completion time (timestamp in milliseconds) - **outerOrderSn** (String) - Required - Merchant’s original payment number related to the refund - **eventType** (String) - Required - Type of refund webhook event: "MERCHANT"= refund initiated by the merchant, "PAY_DUPLICATION"= refund for duplicate payments, "PAY_EXPIRED" = refund for expired payments - **refundType** (String) - Required - Refund channel types - **refundCurrency** (String) - Required - Currency of refund order - **address** (String) - Optional - Refund wallet address (returned only for Web3 decentralized payments) ### Request Example { "refundSn": "RE2025121402253023...", "merchantRefundSn": "TestRefund20251201...", "merchantId": 2135213432, "status": "SUCCESS", "completeTime": 1768357531591, "outerOrderSn": "test-quick-pay-1768301309...", "refundType": "redotpay", "createTime": 1768354530000, "refundAmount": 0.01001, "refundCurrency": "USDT", "eventType": "MERCHANT" } ``` -------------------------------- ### Payment Webhook Notification Source: https://redotpay.readme.io/docs/webhook The payment webhook is a notification sent to the merchant's server to inform them about the status of a payment transaction. ```APIDOC ## Payment Webhook ### Description This webhook notifies the merchant server about payment status updates. It provides details regarding the order, transaction, and payment outcome. ### Request Body - **outerOrderSn** (String) - Required - Merchant’s original order number - **orderSn** (String) - Required - Prepayment serial number - **orderCurrency** (String) - Required - Order's fiat currency - **fiatCurrency** (String) - Required - Bill's fiat currency - **outerUid** (String) - Required - External user ID - **txId** (String) - Required - Channel payment transaction id - **rateExtra** (decimal) - Required - Merchant exchange rate markup - **actionType** (String) - Required - Type of payment webhook action (Always "ACQUIRER_PAY") - **billAmount** (decimal) - Required - Bill's fiat amount - **orderAmount** (decimal) - Required - Order's fiat amount - **orderTime** (long) - Required - Order creation time in milliseconds - **merchantId** (long) - Required - Merchant's unique ID - **cryptoAmount** (decimal) - Required - Total crypto currency amount of orders - **rate** (String) - Required - Fiat to cryptocurrency exchange rates - **paymentMethod** (String) - Required - Payment selection wallet name - **timeExpire** (long) - Required - Payment deadline in milliseconds - **sn** (String) - Required - Payment serial number - **paymentTime** (long) - Required - Successful payment completion time in milliseconds - **orderStatus** (int) - Required - Payment status: 1=Paying, 2=Success, 3=Payment failed, 4=Payment closed - **clientIp** (String) - Required - Buyer's terminal IP - **source** (String) - Required - Buyer's source: H5/APP/WEB ### Request Example { "outerOrder": "T300088...", "preSn": "RAP202601051045558385...", "orderCurrency": "USD", "billCoin": "USD", "outerUid": "T3111...", "txId": "PAYH20260105104613401...", "rateExtra": 0, "actionType": "ACQUIRER_PAY", "billAmount": 0.99, "orderAmount": 1, "orderTime": 1767609970940, "merchantId": 3000000, "cryptoAmount": 1, "rate": 1, "walletName": "redotpay", "paymentDeadline": 1767611755616, "sn": "RA20260105104610940923...", "paymentTime": 1767609973423, "orderStatus": 2, "coin": "USDT", "clientIp": "13.230.109.247", "source": "WEB" } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.