사용 가이드

앱 켜고, 내 사이트 주소만 넣으면 됩니다

입금 문자가 오면 FastPayPush가 그 내용을 내 사이트로 보냅니다. 입금자명·금액이 대기 건과 같으면 입금완료·포인트까지 사이트가 알아서 처리합니다.

앱에서 하는 일

패스트래픽 게시판 아이디는 필요 없습니다. 계정은 휴대폰 또는 기기코드입니다.

1. 권한

알림 접근을 켜고, 배터리 최적화를 제외합니다. 꺼져 있으면 입금을 읽지 못합니다.

2. 계정 탭

내 사이트 주소를 넣고 저장합니다. 연결 테스트로 길이 통하는지 확인할 수 있습니다.

3. 연결 탭

받을 은행을 켭니다. 목록이 비었으면 제목 오른쪽 새로고침을 누릅니다.

4. 전달 다음 — 사이트가 알아서 처리

앱이 입금 알림을 사이트로 보내는 것으로 끝이 아닙니다. 사이트는 입금자명과 금액이 입금 대기 건과 같은지 맞춥니다. 같으면 주문을 입금완료로 바꾸고, 포인트·이용권을 넣습니다. 패스트래픽은 세금발행 요청이 있으면 그다음도 같이 진행합니다. 관리자가 입금 내역을 하나씩 눌러 확인할 필요가 없습니다.

안 맞으면 목록에만 남습니다. 이름이나 금액이 다르면 자동 처리되지 않습니다.

FastPayPush 전체 흐름: 설치, 주소, 은행, 전달, 자동 입금·포인트
한눈에 보는 흐름 — 마지막이 자동 입금완료·포인트입니다
FastPayPush 소개 커버
소개 커버
내 사이트 주소를 넣는 화면
1. 내 사이트 주소 넣기
휴대폰 인증
2. 휴대폰 인증
받을 은행 켜기
3. 받을 은행 켜기
입금이 사이트로 갔는지 확인
4. 사이트로 전달 확인
자동 입금·포인트까지 이어지는 흐름
5. 자동 입금·포인트

사이트가 받는 형식

앱은 HTTPS POST (application/x-www-form-urlencoded) 로 보냅니다. 성공이면 JSON으로 답하면 됩니다.

필드의미
BnakName은행·앱 코드 (철자 그대로)
regPkey앱 계정 mid. 복호화 키로 씁니다.
MNO입금 식별값
ugrd재시도 등 부가값
rtpayDataAES-256-CBC + Base64 암호문

키: mid에서 - 제거 후 앞 32글자. IV: 16바이트 0. 평문: 메시지|Ⓡ|앱코드|Ⓡ|번호

응답 예: {"RCODE":"200","PCHK":"OK"}

기존 RTPay/checkpay 수신 페이지가 있으면 그 URL을 그대로 넣어도 됩니다.

언어별 수신 샘플

자기 사이트에 이 파일을 두고, 앱 계정 탭에 그 주소를 넣으세요. 복사해서 바로 쓸 수 있게 최소 수신만 넣었습니다.

<?php
header('Content-Type: application/json; charset=utf-8');
$mid = (string)($_POST['regPkey'] ?? '');
$enc = (string)($_POST['rtpayData'] ?? '');
$key = substr(str_replace('-', '', $mid), 0, 32);
$raw = base64_decode($enc, true);
$iv = str_repeat("\0", 16);
$plain = openssl_decrypt($raw, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
$parts = explode('|Ⓡ|', (string)$plain);
// $parts[0] 입금 메시지, $parts[1] 앱코드, $parts[2] 번호
echo json_encode(['RCODE' => '200', 'PCHK' => 'OK', 'MSG' => $parts[0] ?? ''], JSON_UNESCAPED_UNICODE);
// Express: npm i express body-parser
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.urlencoded({ extended: true }));

app.post('/paypush', (req, res) => {
  const mid = String(req.body.regPkey || '');
  const enc = String(req.body.rtpayData || '');
  const key = Buffer.from(mid.replace(/-/g, '').slice(0, 32));
  const buf = Buffer.from(enc, 'base64');
  const dec = crypto.createDecipheriv('aes-256-cbc', key, Buffer.alloc(16, 0));
  const plain = Buffer.concat([dec.update(buf), dec.final()]).toString('utf8');
  const [message] = plain.split('|Ⓡ|');
  res.json({ RCODE: '200', PCHK: 'OK', MSG: message || '' });
});
app.listen(3000);
# Flask: pip install flask pycryptodome
from flask import Flask, request, jsonify
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import base64

app = Flask(__name__)

@app.post("/paypush")
def paypush():
    mid = request.form.get("regPkey", "")
    enc = request.form.get("rtpayData", "")
    key = mid.replace("-", "")[:32].encode()
    raw = base64.b64decode(enc)
    plain = unpad(AES.new(key, AES.MODE_CBC, iv=b"\0"*16).decrypt(raw), 16).decode()
    message = plain.split("|Ⓡ|")[0]
    return jsonify(RCODE="200", PCHK="OK", MSG=message)
// Spring: POST /paypush, application/x-www-form-urlencoded
@PostMapping("/paypush")
public Map<String, String> paypush(
    @RequestParam String regPkey,
    @RequestParam String rtpayData
) throws Exception {
    String keySrc = regPkey.replace("-", "");
    byte[] key = keySrc.substring(0, 32).getBytes(StandardCharsets.UTF_8);
    byte[] raw = Base64.getDecoder().decode(rtpayData);
    Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
    c.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(new byte[16]));
    String plain = new String(c.doFinal(raw), StandardCharsets.UTF_8);
    String message = plain.split("\\|Ⓡ\\|", 2)[0];
    return Map.of("RCODE", "200", "PCHK", "OK", "MSG", message);
}
// ASP.NET Minimal API
app.MapPost("/paypush", async (HttpRequest req) => {
    var form = await req.ReadFormAsync();
    var mid = form["regPkey"].ToString().Replace("-", "");
    var key = Encoding.UTF8.GetBytes(mid[..32]);
    var raw = Convert.FromBase64String(form["rtpayData"]);
    using var aes = Aes.Create();
    aes.Key = key; aes.IV = new byte[16]; aes.Mode = CipherMode.CBC;
    aes.Padding = PaddingMode.PKCS7;
    var plain = Encoding.UTF8.GetString(aes.CreateDecryptor().TransformFinalBlock(raw, 0, raw.Length));
    var message = plain.Split("|Ⓡ|")[0];
    return Results.Json(new { RCODE = "200", PCHK = "OK", MSG = message });
});
// net/http
func paypush(w http.ResponseWriter, r *http.Request) {
    r.ParseForm()
    mid := strings.ReplaceAll(r.FormValue("regPkey"), "-", "")
    key := []byte(mid[:32])
    raw, _ := base64.StdEncoding.DecodeString(r.FormValue("rtpayData"))
    block, _ := aes.NewCipher(key)
    dec := cipher.NewCBCDecrypter(block, make([]byte, 16))
    buf := append([]byte{}, raw...)
    dec.CryptBlocks(buf, buf)
    // PKCS7 unpad 후 strings.Split(string(buf), "|Ⓡ|")[0]
    w.Header().Set("Content-Type", "application/json")
    w.Write([]byte(`{"RCODE":"200","PCHK":"OK"}`))
}