# Request signing

> Learn the two Transfer API signing methods and their examples.

Transfer APIs provide two signing methods: `SHA256withRSA` and `SHA256`. Use the method assigned to your merchant by Onerway.

## Before you start

<note>

Confirm your merchant's signing method first. The signing key type, canonical string rule, and generated signature format differ between the two methods.

</note>

## SHA256withRSA

### Signing steps

1. Obtain the `privateKey`
2. Use the `SHA256withRSA` algorithm
3. Convert the canonical string into UTF-8
4. Generate the signature
5. Base64-encode the signature result

### Canonical string rule

Remove all parameters whose values are empty, sort the remaining parameters by ASCII order of the parameter name, and concatenate them in the format `key=value&key1=value1...`. Do not append `&` after the last parameter.

### Example private key

```text
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDHaM7clWWlJNS6
ZR5ZkxSFeMMFt74YGRmYPr67UHrfc4CzFtN9sctIUqZJVv05sfOgnb0rk1G7wx97
/LqxPEGs5chc+Nq9HkNf5VopMifOQ85j1Sv1U031oEGk+Oi4MTAR4ZWlLKBQPyKV
b5pCP8aIv15GTIiIwJKS17zY5mQUrXzASTDk54DCG9eN4Lgka9xzwRvaYZvmxLg7
32GxjI5TE797kA5gxY7GxZ0wxdkWkhcee6xX6WWhAcmdHPUUS0EPcnL5wcc3wP07
vO+R/jO1XoaXczb6JRh6ApR3Y5VjSFQApqwe7AIgASGf8aSkBU4K95RfZ3QsBjof
2SX/3fkf
```

### Example request data

```json
{
  "key": "value",
  "key2": "value2",
  "key1": "value2",
  "sign": "RcqXuiVp1JpwJedRGzTpL8M5mUsfeHL29gV9ycaJwmDoNV21AiaQ41au2qiJ8h+jKn/KBMcrJAzHGBTO3CZ0ffGxmqNz9fKhZX+X1MTntH+MhtKTyKR4ZF8kbAtezdVgPfqT69NPQGbWo57R3KP0m4W4n2ZjgkxkcG3yYtBdAgsyxDNoT8W0wH7nK7Y0zp88O8wIMe7kfBnK59J4y0Xz2EwiFX+bNkfRhf3U5WiHIU2TdRbaYsnzndmOkYkVdFAiUH7zoXnEn8ZVqiDZkK4eFG9H1LxU55dStug1hLtwxOKlu5OYFUi4iGAiq0Vlir01eDR1++KAudOdb1gcUyH2rA=="
}
```

### Example canonical string

```text
key=value&key1=value2&key2=value2
```

### Example signature result

```text
RcqXuiVp1JpwJedRGzTpL8M5mUsfeHL29gV9ycaJwmDoNV21AiaQ41au2qiJ8h+jKn/KBMcrJAzHGBTO3CZ0ffGxmqNz9fKhZX+X1MTntH+MhtKTyKR4ZF8kbAtezdVgPfqT69NPQGbWo57R3KP0m4W4n2ZjgkxkcG3yYtBdAgsyxDNoT8W0wH7nK7Y0zp88O8wIMe7kfBnK59J4y0Xz2EwiFX+bNkfRhf3U5WiHIU2TdRbaYsnzndmOkYkVdFAiUH7zoXnEn8ZVqiDZkK4eFG9H1LxU55dStug1hLtwxOKlu5OYFUi4iGAiq0Vlir01eDR1++KAudOdb1gcUyH2rA==
```

<code-collapse>

```xml
<dependency>
  <groupId>commons-codec</groupId>
  <artifactId>commons-codec</artifactId>
  <version>1.14</version>
</dependency>
```

```java
package xxx;

import org.apache.commons.codec.binary.Base64;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;

public class RSASecureDemo {
    public static String signRSA(String privateKey, String toBeSignedData) {
        try {
            byte[] keyBytes = Base64.decodeBase64(privateKey);
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
            Signature signature = Signature.getInstance("SHA256withRSA");
            signature.initSign(priKey);
            signature.update(toBeSignedData.getBytes(StandardCharsets.UTF_8));
            return Base64.encodeBase64String(signature.sign());
        } catch (Exception e) {
            throw new RuntimeException("rsa sign failed");
        }
    }

    public static void main(String[] args) {
        String privateKey = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDHaM7clWWlJNS6" +
            "ZR5ZkxSFeMMFt74YGRmYPr67UHrfc4CzFtN9sctIUqZJVv05sfOgnb0rk1G7wx97" +
            "/LqxPEGs5chc+Nq9HkNf5VopMifOQ85j1Sv1U031oEGk+Oi4MTAR4ZWlLKBQPyKV" +
            "483/Axmrwea50UKLqRVH3IXzTOEJth0betqTmbefYFLETn5RXB6MOJQOdzpvvcP3" +
            "05FmtT/grqqcnaeLbosT4A==";

        String toBeSignedData = "key=value&key1=value2&key2=value2";
        String sign = signRSA(privateKey, toBeSignedData);
        System.out.println(sign);
    }
}
```

</code-collapse>

## SHA256

### Signing steps

1. Obtain the secret key
2. Concatenate the canonical string and the secret key as strings
3. Convert the result into UTF-8
4. Apply the `SHA-256` digest
5. Convert the digest into a hexadecimal string

### Canonical string rule

Remove all parameters whose signing column is `No` and parameters whose values are empty. Sort the remaining parameters by ASCII order of the parameter name, concatenate only the parameter values, and then append the secret key.

### Example secret key

```text
3b5e10b65bff4172a5b9ca2d2ec00a6e
```

### Example request data

```json
{
  "merchantNo": "800135",
  "test": "dsaaass1dsag",
  "bizContent": "yesdas1dsa",
  "as": "12334567",
  "bc": "098754"
}
```

### Example canonical string

```text
12334567098754yesdas1dsa800135dsaaass1dsag
```

### Example signature result

```text
0ce84cc90742e79b3af76da6b6909dc158a2e933057562639fe6a5a8e73f5350
```

<code-collapse>

```xml
<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-lang3</artifactId>
  <version>3.6</version>
</dependency>
```

```java
package xxx;

import org.apache.commons.lang3.StringUtils;
import java.security.MessageDigest;
import java.util.TreeMap;

public class SHA256SecureDemo {
    public static void main(String[] args) throws Exception {
        TreeMap data = new TreeMap();
        data.put("merchantNo","800135");
        data.put("test","yesdas1dsa");
        data.put("bizContent","dsaaass1dsag");
        data.put("as","12334567");
        data.put("bc","098754");

        String toBeSignedData = strcatValueSign(data);
        String key = "3b5e10b65bff4172a5b9ca2d2ec00a6e";
        String sign = signSha256(key, toBeSignedData);
        System.out.println(sign);
    }

    private static String strcatValueSign(TreeMap treeMap) {
        StringBuffer buffer = new StringBuffer();
        treeMap.forEach((k, v) -> {
            if (StringUtils.isNotBlank((String) v)) {
                buffer.append(v);
            }
        });
        return buffer.toString();
    }

    public static String signSha256(String key, String toBeSignedData) {
        String str = toBeSignedData + key;
        String encodestr = "";
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.update(str.getBytes("UTF-8"));
            encodestr = byte2Hex(messageDigest.digest());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return encodestr;
    }

    private static String byte2Hex(byte[] bytes) {
        StringBuffer stringBuffer = new StringBuffer();
        String temp = null;
        for (int i = 0; i < bytes.length; i++) {
            temp = Integer.toHexString(bytes[i] & 0xFF);
            if (temp.length() == 1) {
                stringBuffer.append("0");
            }
            stringBuffer.append(temp);
        }
        return stringBuffer.toString();
    }
}
```

</code-collapse>

## Next Steps

- [Setup](/transfer/get-started)
- [Integration flow](/transfer/get-started/integration-flow)
- [Testing and go-live](/transfer/get-started/testing-and-go-live)
