Points Code (1.0)

Introduction

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:

  • Create Points Code (charge code) for an end user instantly
  • Check your remaining Deposit Balance (budget) This document will be focusing on APIs that support the above functionalities.

Onboard merchant

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:

  • API key and secret
  • Allowed authorization callback domains
  • Client IP whitelist This setup can be managed using our merchant panel or by getting in touch with a sales representative. For Points Code API, it also requires creation of Points Code 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.

Specify merchant in request

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.

Api Authentication

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.

Parameters considered for 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 string
Note : 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==

Steps to genererate HMAC auth header

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 and
For 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.

Error Handling

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.

Response code list

Common response code

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.

Create Points Code

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.

Points Code APIs

Create Points Code

Create new Points Code. For timeout and internal error(5XX HTTP status codes) , merchants can safely retry the request with same requestId.

Timeout: 30s

Request Body schema: application/json
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
Be sure to set over 100 when balance type is PREPAID

startAt
required
string <yyyy-MM-dd>
endAt
required
string <yyyy-MM-dd>

Responses

Request samples

Content type
application/json
{
  • "requestId": "ea233cbd-f949-42f3-98e7-ddd1cb5e6ffd",
  • "groupId": 29952775505428480,
  • "giftCardName": "Points Code 01",
  • "giftCardValue": 1000,
  • "startAt": "2021-10-10",
  • "endAt": "2022-10-09"
}

Response samples

Content type
application/json
{
  • "resultInfo": {
    },
  • "data": {
    }
}

Get group budget

Get all groups budget based on merchant.

Timeout: 15s

Responses

Response samples

Content type
application/json
{
  • "resultInfo": {
    },
  • "data": {
    }
}