PayPay Points Code API is designed to be used by our partners to perform Points Code related operations so as to deliver the best experience to end users. After being onboarded as a PayPay Client,you will have the following capabilities:
To start utilizing our Open API platform, first the business needs to be onboarded as a PayPay merchant. This process usually consists of information collection, manual verification, contract confirmation and credentials issuance. After becoming a merchant on PayPay, the following items would be set up for the client:
groupId
. Merchants are allowed to have multiple Points Code groupId
based on the business requirement.
The operation of creating Points Code groupId
needs to be set up by your sales representative.
Access by users to the PayPay app and PayPay web screen from outside Japan is restricted. Please contact us for details.Every time an API is called, the merchant identifier needs to be passed along with the request. There are two ways to pass the merchant identifier:
In a query string parameter:
?assumeMerchant={MerchantId}
Or in HTTP headers:
X-ASSUME-MERCHANT: {MerchantId}
If both are provided, the query string parameter would take precedence.
All the following APIs need to be called via HMAC. For the implementation of HMAC based authentication, entire request is taken into account for building authentication object.
Value | Description | Example |
---|---|---|
API Key | API key generated | APIKeyGenerated |
API Key secret | API Key secret generated | APIKeySecretGenerated |
Request URI | Service request URL path | /v2/codes |
Request method | HTTP method | POST |
Epoch | Current epoch seconds, Note : Validated whether less than 2mins on server side | 1579843452 |
Nonce | Random generated stringNote : String of any length, but recommended to use of length 8 | acd028 |
Request body | Value of request body passed in request | {"sampleRequestBodyKey1":"sampleRequestBodyValue1","sampleRequestBodyKey2":"sampleRequestBodyValue2"} |
Request content type | Content type passed in request header | application/json;charset=UTF-8; |
hash (MD5(Request body, Request content type)) | Hash of request body and content type. This will be the output from step 1 of genererating HMAC auth header added below | 1j0FnY4flNp5CtIKa7x9MQ== |
Sample HMAC Auth header generated from above example values is as followed
hmac OPA-Auth:APIKeyGenerated:NW1jKIMnzR7tEhMWtcJcaef+nFVBt7jjAGcVuxHhchc=:acd028:1579843452:1j0FnY4flNp5CtIKa7x9MQ==
Step 1: Hash the body and content-type with MD5 algorithm
Code sample for hashing body and content type
private String requestBody;
private String contentType;
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(contentType.getBytes(StandardCharsets.UTF_8));
md.update(requestBody.getBytes(StandardCharsets.UTF_8));
String hash = new String(
Base64.getEncoder().encode(md.digest()),
StandardCharsets.UTF_8);
Note : If there is no request body, for instance, the HTTP GET method case, no need of generating MD5. Instead hash value is set as "empty".
Step 2 : Build string to be hashed with HMAC-SHA256.
We will consider following parameters for signing the request
private String requestUrl; //Only the request URI Example: "/v2/codes/payments/dynamic-qr-test-00002"
private String httpMethod;
private String nonce; //Random string
private String epoch;
private String contentType;
private String hash; //Output of step 1
private static final String DELIMITER = "\n";
byte[] hmacData = new StringBuilder()
.append(requestUrl)
.append(DELIMITER)
.append(httpMethod)
.append(DELIMITER)
.append(nonce)
.append(DELIMITER)
.append(epoch)
.append(DELIMITER)
.append(contentType)
.append(DELIMITER)
.append(hash != null ? hash : "")
.toString()
.getBytes(StandardCharsets.UTF_8);
Note : If there is no request body, for instance, the HTTP GET method case, content-type and hash will be set as "empty".
Step 3 : Generating HMAC object Generate HMAC based on output from Step 2 and Key secret of API key secret pair.
public final String toBase64HmacString() {
private String apiKeySecret;
private byte[] dataToSign; //Output from step 2
try {
SecretKeySpec signingKey = new SecretKeySpec(apiKeySecret.getBytes(StandardCharsets.UTF_8),
"HmacSHA256");
Mac sha256HMAC = Mac.getInstance("HmacSHA256");
sha256HMAC.init(signingKey);
byte[] rawHmac = sha256HMAC.doFinal(dataToSign);
return java.util.Base64.getEncoder().encodeToString(rawHmac);
} catch (GeneralSecurityException e) {
LOGGER.error("Unexpected error while creating hash: " + e.getMessage());
throw new IllegalArgumentException(e);
}
}
Step 4 : Build header object with the parameters of syntax. //We will be using password as the key to sign the hmacData
String authHeader = "hmac OPA-Auth:" + api-key +
":" + macData + ":" + nonce + ":" + epoch + ":" + hash;
Note: macData is output from step 3 andFor nonce and epoch, same value that has been used in step 2 should be passed.
If there is no body of the request such as in the case of HTTP GET method, the hash value will be "empty", so the header object will be as follows.
String authHeader = "hmac OPA-Auth:" + api-key +
":" + macData + ":" + nonce + ":" + epoch + ":empty";
The value of authHeader is passed in HttpHeader.AUTHORIZATION. With the authHeader will decode back the data added and with the HTTP request object and based on data available for api-key in the system, we will recreate the SHA256("key", requestParams) which gives macData. This macData is verified against the value passed in the header.
PayPay OPA uses HTTP response status codes and OPA error codes to indicate the success or failure of requests. With this information, you can decide what error handling strategy to use. In general, PayPay OPA returns the following HTTP response status codes.
Status | Code | Description |
---|---|---|
200 | SUCCESS | Success |
400 | INVALID_REQUEST_PARAMS | The information provided by the request contains invalid data, e.g., unsupported currency. |
400 | MISSING_REQUEST_PARAMS | The set parameter is invalid. |
401 | UNAUTHORIZED | No valid api key and secret provided |
401 | OP_OUT_OF_SCOPE | The operation is not permitted. |
404 | OPA_CLIENT_NOT_FOUND | OPA Client not found |
429 | RATE_LIMIT | Too many requests |
500 | SERVICE_ERROR | A service error has occurred. |
500 | INTERNAL_SERVER_ERROR | This code means that something went wrong, but we don't know exactly if the transaction has happened or not. It should be treated as unknown payment status. |
503 | MAINTENANCE_MODE | Sorry, we are down for scheduled maintenance. |
Status | Code | Description |
---|---|---|
400 | BUDGET_NOT_ENOUGH | Points Code group doesn't have enough budget. |
400 | EXCEED_CHARGE_CODE_GROUP_MAX_PERIOD | The period between startAt and endAt is over group maxPeriodDays setting |
400 | GIFT_CARD_GROUP_NOT_EXIST | Points Code group does not exist. |
400 | INVALID_CHARGE_CODE_AMOUNT | Points Code value is less then minimum limit amount. |
Create new Points Code. For timeout and internal error(5XX HTTP status codes) , merchants can safely retry the request with same requestId.
Timeout: 30s
requestId required | string RequestId will be the idempotency key for creating Points Code |
groupId required | integer <int64> |
giftCardName required | string Points Code name which will be displayed in PayPay app after user tops up |
giftCardValue required | integer <int32> [ 1 .. 999999 ] Value of the Points Code in JPY |
startAt required | string <yyyy-MM-dd> |
endAt required | string <yyyy-MM-dd> |
{- "requestId": "ea233cbd-f949-42f3-98e7-ddd1cb5e6ffd",
- "groupId": 29952775505428480,
- "giftCardName": "Points Code 01",
- "giftCardValue": 1000,
- "startAt": "2021-10-10",
- "endAt": "2022-10-09"
}
{- "resultInfo": {
- "code": "string",
- "message": "string",
- "codeId": "string"
}, - "data": {
- "groupId": 29952775505428480,
- "giftCardName": "Points Code name",
- "giftCard": "MYOG-6BKL-CRPP-19U7",
- "giftCardValue": 1000,
- "startAt": "2021-10-10",
- "endAt": "2022-10-09",
- "inquiryNumber": 706637276862275600
}
}
{- "resultInfo": {
- "code": "string",
- "message": "string",
- "codeId": "string"
}, - "data": {
- "merchantId": 13145928525414400,
- "groups": [
- {
- "id": 29952775505428480,
- "name": "Points Code group name",
- "balanceType": "CASHBACK",
- "maxPeriodDays": 365,
- "chargeLimit": 5,
- "status": "enable",
- "totalBudget": 10000,
- "remainingBudget": 10000
}
]
}
}