Skip to main content

การยืนยันตัวตนด้วยลายเซ็นดิจิทัล

ประมาณ 3 นาที

ภาพรวมลายเซ็นดิจิทัล

การยืนยันตัวตนด้วยลายเซ็นดิจิทัลเป็นกลไกด้านความปลอดภัยที่สำคัญสำหรับธุรกรรม API ทั้งหมด รวมถึงการดำเนินการ Pay-In, Pay-Out และ Inquiry (ตรวจสอบสถานะและตรวจสอบยอดคงเหลือ) กระบวนการนี้รับประกันความสมบูรณ์ ความถูกต้องแท้จริง และการปฏิเสธไม่ได้ของคำขอผ่านการตรวจสอบเชิงการเข้ารหัส

ใช้ได้กับทุก API ที่ต้องลงนาม

ทุกคำขอ Pay-In, Pay-Out และ Inquiry ต้องมี header X-TIMESTAMP, X-SIGNATURE และ X-PARTNER-ID กฎการลงนามในหน้านี้ตรงกับเอกสารอ้างอิง คำขอ Pay-In

กระบวนการสร้างลายเซ็น

เตรียมข้อมูลสำหรับลายเซ็น

รวบรวมองค์ประกอบต่อไปนี้สำหรับการสร้างลายเซ็น:

  • X-TIMESTAMP: เวลาในรูปแบบ ISO 8601 (เช่น 2024-12-30T18:30:36+07:00)
  • Merchant Secret: คีย์ลับของร้านค้าที่ได้รับมอบหมายให้คุณ
  • Request Body: เพย์โหลด JSON (จะถูกย่อให้สั้น)
  • Merchant Private Key: คีย์ส่วนตัว RSA ของคุณสำหรับลงนาม (PKCS#8, Base64)

Signature Parameters

ย่อ Request Body

ลบช่องว่างและการจัดรูปแบบที่ไม่จำเป็นทั้งหมดออกจาก request body แบบ JSON เพื่อให้การสร้างลายเซ็นมีความสอดคล้องกัน

{
    "area": 10,
    "callbackUrl": "https://docs.smilepayz.com/en/",
    "merchant": {
        "merchantId": "20019"
    },
    "money": {
        "amount": 10000,
        "currency": "IDR"
    },
    "orderNo": "20019c5b63c4b-e34a-4855-9b20-d4b",
    "paymentMethod": "QRIS",
    "purpose": "Purpose For Transaction from Java SDK"
}

ห้ามเปลี่ยน body หลังจากลงนามแล้ว

สร้างลายเซ็นจากสตริง JSON แบบย่อที่จะถูกส่งใน HTTP body จริงเท่านั้น การเปลี่ยนแปลงใด ๆ หลังจากลงนามแล้วจะทำให้การตรวจสอบล้มเหลว

ประกอบสตริงสำหรับลงนาม

สร้างสตริงลายเซ็นโดยการเชื่อมต่อองค์ประกอบต่าง ๆ ด้วยตัวคั่นไปป์ (|):

X-TIMESTAMP + "|" + merchant_secret + "|" + minify(requestBody)

ตัวอย่างสตริงสำหรับลงนาม

2024-12-30T18:30:36+07:00|95b57c46b8c2e068982be23fb669a80612cad68e6ce6ba4f5af9ec20d23bb274|{"area":10,"callbackUrl":"https://docs.smilepayz.com/en/","merchant":{"merchantId":"20019"},"money":{"amount":10000,"currency":"IDR"},"orderNo":"20019c5b63c4b-e34a-4855-9b20-d4b","paymentMethod":"QRIS","purpose":"Purpose For Transaction from Java SDK"}

สร้างลายเซ็นดิจิทัล

ใช้ SHA256withRSA กับสตริงสำหรับลงนามโดยใช้คีย์ส่วนตัว RSA ของคุณ

สูตรการเข้ารหัส

SHA256withRSA(stringToSign, merchantPrivateKey)
ตัวอย่างคีย์ส่วนตัว RSA (PKCS#8, Base64)
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC1d8Zaurk/A0WB1X7CrW+SqsVM4v2ZMGTdqWEQOAKQyY/DZEmgSm7whUMLYfqeKxzzAd3lZHvviyO/V/Ht2i8axtiA5tyDa485IgBy+jO9UHxzI+9CRxnIY5jjDAqAgEvRa0HZEfYHLGlH3IQ4A2a7g8Wm3yqn2prIrgY21nO4+33GuBR0qCpGxth0kV7/RSdhWv3Ff1zkb7yUYn9zfuag9stLf1nw+Ui7hjXL+xGiNRYsDCHOLzKynZxk1cBfqyPY5YMTIjQik4cI+YfM4BMN8bmTB1y3z9sdfbHVTI/PD/fbDzvfK7S/XJvY2bj1TwNeYCHcd5Dx6MYiO12rfA5XAgMBAAECggEASRpMJMat042c1ZXM793wYXQ78SJMKQcOyyDtwhveJLeeG4duBY2WrXvxq0c4L7mMevSYkE1vg+tYZj+mbTwE19Oc6iiWUrbkxo5FAgx7BVvEFpo2S0vbPhepQmXaYTPN1zpPF4QdyXwBmXpjJTFxlD6cRAII6/+rdQZt6G9xxOWUq6bbENNUc6y+N+97oPPwrzLZGYADfusM735Mlx3j8xTGLSHTh2d8e5epwKcSW+ZvBbiM30ZeO+M5bh6zgZrHpPQNJAOsEDuVk5vjuC5O+i81YwP702GAE50zI9Ysr4QMS3QQGe2jwpJAmMjvO6/MRv/6De83NJ6Y70+00OONcQKBgQDtP+sQOyKRErCN9ePmu6FBfzMZcTC5vXQpA0kW7vUMKyQR537appYcOb5DPJDgUqqyNcr8vIqadR6OW0thkfRyb+L/elOyS/XnVbFc6RA9DW/KV4xm68LUX9oRqfgy5YOESEEA2igEh8IdqfkIRCZ3g7xrQUmb3gq0BM2/hnxyHwKBgQDDz0Slbw2Pv820CSheZi8HQf3sEFe0JDHKo2KAHX9rTvFEF3xsT+UZh6pcHUcesYlVlJM2Ciejq4dmiOnvGIKtkqtcLfioVbPrDP2HlDtIT3mSC7sL6VdWLxYz/l0EVjsR2KMVwXD42jcjz3e5bDIi98Z8G4Bx6cu6pwlBtfMMyQKBgHJhWoacu/GNPSlz3sgitX/KP2yIsaEawaH0P4ya7/FJ6z3mibYIkl5RSHVKAd7ke/8nCBIJJBmLVYv0X8dOgreZUasx4qAXFxrMqZHNm1KT4819n+cOywNwosXZWBvRozJnU0+B3cExYljC1ZkyogkErhZXh5Fp32ci2b74q46pAoGANWyixSRkpdjmLf3lpsPohulpd3QKCdtqPmiPonbp4gRa7YIe74po7qtGPvW6BtTXrKLp+2+P2yccvUwTz6l3VhZTbMYaNwuTGEmmDszR0+vjNoa+1QQoURpty2fWRy2j1j2uWWw6/5rCOqILf2rWzxWdcRUr2Wi5rkaOzv/uvYkCgYEAlFV6huNhi1NIIg5gkTS0kmxnIUWu8XIT9IgZWMrhR7TvImVISoormE9LdISgMBz+J5YJxhAZbxVxlUJrsl+HVcS81gmUkeoIpTA+iKUzbD9gAPjEdqVylzN8A9uNIkkb5Cf4BWYfEyMaLfBuiHDlKDcBjz4cJbcom3RVGacghKc=
ตัวอย่างลายเซ็นที่สร้างขึ้น
BD+qFc0/JOl1grDKSs0zMumPeswzLN/tVj/bms9AYZdVwtzZ3RQJ2gdCxtMeF/fYVTLOZZVLiKnFm0KDjoChl9Kz+6VpgFCMCQt99iUxoJxLtCvPhlCdD1rHVNfrNWKt4mLSNdQWmh//hlwP4AJqidMUKCTDMDm2ivgvQqMIFqdadITAreevKQ+VZs7ukZMzo5BgYfdhCiorAqAb/EUN1/O0pDt8Uv+xcL4QNxxu1dj10UDRbHaox4Qv1tfXbRoiisNa9xAlVkd3l19FW/Mv09jkDEKL+x5uIx3WjGY81NyVW6yxx5jEbsZbdl5KfqA6SwKpc3IOVLwR4J4Q0jaFGA==

ตัวอย่างโค้ด

import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;

public class SignatureExample {

    /** Build X-SIGNATURE for Smilepayz APIs. */
    public static String sign(
            String timestamp,
            String merchantSecret,
            String minifiedRequestBody,
            String privateKeyBase64) throws Exception {
        String stringToSign = timestamp + "|" + merchantSecret + "|" + minifiedRequestBody;

        byte[] keyBytes = Base64.getDecoder().decode(privateKeyBase64);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec);

        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(stringToSign.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(signature.sign());
    }
}

ใส่ลายเซ็นใน HTTP Header

เพิ่มลายเซ็นที่สร้างขึ้นลงใน HTTP request header พร้อมกับ timestamp และ merchant ID:

Content-Type: application/json
X-TIMESTAMP: 2024-12-30T18:30:36+07:00
X-SIGNATURE: BD+qFc0/JOl1grDKSs0zMumPeswzLN/tVj/bms9AYZdVwtzZ3RQJ2gdCxtMeF/fYVTLOZZVLiKnFm0KDjoChl9Kz+6VpgFCMCQt99iUxoJxLtCvPhlCdD1rHVNfrNWKt4mLSNdQWmh//hlwP4AJqidMUKCTDMDm2ivgvQqMIFqdadITAreevKQ+VZs7ukZMzo5BgYfdhCiorAqAb/EUN1/O0pDt8Uv+xcL4QNxxu1dj10UDRbHaox4Qv1tfXbRoiisNa9xAlVkd3l19FW/Mv09jkDEKL+x5uIx3WjGY81NyVW6yxx5jEbsZbdl5KfqA6SwKpc3IOVLwR4J4Q0jaFGA==
X-PARTNER-ID: 20019

ตัวอย่าง cURL (Sandbox Pay-In)

curl -X POST 'https://sandbox-gateway.smilepayz.com/v2.0/transaction/pay-in' \
  -H 'Content-Type: application/json' \
  -H 'X-TIMESTAMP: 2024-12-30T18:30:36+07:00' \
  -H 'X-SIGNATURE: BD+qFc0/JOl1grDKSs0zMumPeswzLN/tVj/bms9AYZdVwtzZ3RQJ2gdCxtMeF/fYVTLOZZVLiKnFm0KDjoChl9Kz+6VpgFCMCQt99iUxoJxLtCvPhlCdD1rHVNfrNWKt4mLSNdQWmh//hlwP4AJqidMUKCTDMDm2ivgvQqMIFqdadITAreevKQ+VZs7ukZMzo5BgYfdhCiorAqAb/EUN1/O0pDt8Uv+xcL4QNxxu1dj10UDRbHaox4Qv1tfXbRoiisNa9xAlVkd3l19FW/Mv09jkDEKL+x5uIx3WjGY81NyVW6yxx5jEbsZbdl5KfqA6SwKpc3IOVLwR4J4Q0jaFGA==' \
  -H 'X-PARTNER-ID: 20019' \
  -d '{"area":10,"callbackUrl":"https://docs.smilepayz.com/en/","merchant":{"merchantId":"20019"},"money":{"amount":10000,"currency":"IDR"},"orderNo":"20019c5b63c4b-e34a-4855-9b20-d4b","paymentMethod":"QRIS","purpose":"Purpose For Transaction from Java SDK"}'

Sandbox base URL

Sandbox: https://sandbox-gateway.smilepayz.com · Production: https://gateway.smilepayz.com ดู URL ของแต่ละสภาพแวดล้อม

การตรวจสอบลายเซ็น

ใช้คีย์สาธารณะ RSA ด้านล่างเพื่อตรวจสอบ callback หรือเพื่อยืนยันลายเซ็นระหว่างการทดสอบการเชื่อมต่อ

คีย์สาธารณะ RSA สำหรับการตรวจสอบ
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtXfGWrq5PwNFgdV+wq1vkqrFTOL9mTBk3alhEDgCkMmPw2RJoEpu8IVDC2H6nisc8wHd5WR774sjv1fx7dovGsbYgObcg2uPOSIAcvozvVB8cyPvQkcZyGOY4wwKgIBL0WtB2RH2ByxpR9yEOANmu4PFpt8qp9qayK4GNtZzuPt9xrgUdKgqRsbYdJFe/0UnYVr9xX9c5G+8lGJ/c37moPbLS39Z8PlIu4Y1y/sRojUWLAwhzi8ysp2cZNXAX6sj2OWDEyI0IpOHCPmHzOATDfG5kwdct8/bHX2x1UyPzw/32w873yu0v1yb2Nm49U8DXmAh3HeQ8ejGIjtdq3wOVwIDAQAB

เครื่องมือสำหรับการพัฒนา

เครื่องมือย่อ JSON

เครื่องมือURLวิธีใช้
JSON Formatterhttps://jsonformatter.org/json-minifyopen in new windowเลือกตัวเลือก "Minify JSON"

แนวทางปฏิบัติที่ดีด้านความปลอดภัย

การจัดการคีย์

  • การจัดเก็บอย่างปลอดภัย: จัดเก็บคีย์ส่วนตัวในที่จัดเก็บที่ปลอดภัยและเข้ารหัส
  • การหมุนเวียนคีย์: หมุนเวียนคู่คีย์ RSA อย่างสม่ำเสมอ
  • การควบคุมการเข้าถึง: จำกัดการเข้าถึงคีย์ส่วนตัวเฉพาะบุคลากรที่ได้รับอนุญาตเท่านั้น
  • การสำรองข้อมูล: เก็บข้อมูลสำรองของคีย์ส่วนตัวอย่างปลอดภัย

แนวทางการพัฒนา

ช่วงเวลาของ Timestamp

ตรวจสอบให้แน่ใจว่า X-TIMESTAMP อยู่ภายใน ±5 นาที ของเวลาเซิร์ฟเวอร์ Smilepayz ซิงค์นาฬิการะบบของคุณกับเซิร์ฟเวอร์ NTP

ความสมบูรณ์ของคำขอ

ห้ามแก้ไข request body หลังจากสร้างลายเซ็นแล้ว สร้างลายเซ็นใหม่หากมีฟิลด์ใดเปลี่ยนแปลง

  • การจัดการข้อผิดพลาด: สร้างการจัดการข้อผิดพลาดที่เหมาะสมสำหรับกรณีตรวจสอบลายเซ็นล้มเหลว
  • การบันทึก Log: บันทึก log ความพยายามในการสร้างลายเซ็นเพื่อวัตถุประสงค์ในการตรวจสอบ (ห้ามบันทึก merchant secret หรือคีย์ส่วนตัว)

ปัญหาที่พบบ่อยและวิธีแก้ไข

  • ลายเซ็นไม่ตรงกัน: ตรวจสอบว่าองค์ประกอบทั้งหมดอยู่ในลำดับและรูปแบบที่ถูกต้อง
  • ปัญหา Timestamp: ตรวจสอบให้แน่ใจว่านาฬิการะบบซิงค์กับเซิร์ฟเวอร์ NTP
  • รูปแบบคีย์: ตรวจสอบรูปแบบและการเข้ารหัสของคีย์ RSA (คีย์ส่วนตัว PKCS#8, Base64)
  • ปัญหาการเข้ารหัสอักขระ: ตรวจสอบให้แน่ใจว่าใช้การเข้ารหัส UTF-8 ที่ถูกต้องสำหรับองค์ประกอบสตริงทั้งหมด

การปฏิบัติตามข้อกำหนดและมาตรฐาน

มาตรฐานการเข้ารหัส

  • อัลกอริทึม: SHA256withRSA (การแฮช SHA-256 ร่วมกับลายเซ็น RSA)
  • ขนาดคีย์: แนะนำคีย์ RSA ขนาดอย่างน้อย 2048 บิต
  • การเข้ารหัส: การเข้ารหัส Base64 สำหรับเอาต์พุตลายเซ็น
  • รูปแบบ: รูปแบบ PKCS#8 สำหรับคีย์ส่วนตัว

ข้อกำหนดด้านการตรวจสอบ

  • Log ลายเซ็น: เก็บ log ของการสร้างและการตรวจสอบลายเซ็นทั้งหมด
  • การใช้งานคีย์: ติดตามการใช้งานคีย์และกำหนดการหมุนเวียน
  • Log การเข้าถึง: ตรวจสอบการเข้าถึงข้อมูลการเข้ารหัส
  • รายงานการปฏิบัติตามข้อกำหนด: จัดทำรายงานการปฏิบัติตามข้อกำหนดสำหรับข้อกำหนดด้านกฎระเบียบ