FaTPay Docs
🇨🇳 中文(简体)
🇨🇳 中文(简体)
  • 介绍
  • 申请集成
    • 成为合作伙伴
    • 快速启动
  • 更多场景的最佳实践
    • 交易所
    • 项目方
    • 钱包工具
    • 流量合作
    • NFT
  • 参考文档
    • 集成 on-ramp 页面
      • 自定义控件
      • 自定义界面
      • 加签
    • 集成 NFT Checkout 页面
    • API 接口文档
      • API
        • 加密货币查询接口
        • 法定货币及支付方式查询接口
        • 报价查询接口
        • 订单列表查询接口
      • Webhooks
        • 订单回调通知
      • 接口加签 & 验签
  • 附录
    • 语言种类
    • 可支持法币
    • 可支持加密货币(on-ramp)
    • 可支持的加密货币(NFT Checkout)
    • API 接口错误码索引
    • RSA 密钥生成指南
    • Demo
      • 集成 FaTPay 页面加签
      • API 接口加签
      • Webhook 订单回调验签
  • 翻译说明
    • 中文翻译
Powered by GitBook
On this page
  1. 附录
  2. Demo

Webhook 订单回调验签

PreviousAPI 接口加签Next中文翻译

Last updated 2 years ago

本文是 的 demo

使用本文代码时,请务必将其中的合作伙伴账号相关信息替换为您自身的

package onramp.webhookvalidation;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import javax.servlet.http.HttpServletRequest;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.X509EncodedKeySpec;
import java.util.*;

/**
 * SignUtil
 *
 * @author FaTPay
 */
public class SignUtil {

    private static final Logger LOG = LoggerFactory.getLogger(SignUtil.class);

    /**
     * Signature algorithms
     */
    public static final String SIGNATURE_ALGORITHM = "SHA256withRSA";

    /**
     * Webhook public key
     */
    private static final String FATPAY_PUBLIC_KEY = "<FaTPay RSA PUBLIC KEY>";

    /**
     * Verifies the signature
     *
     * @param params
     * @param rsaPublic
     * @return
     */
    public static Boolean rsaVerify(Map<String, String> params, String rsaPublic, String presign, String sign) {
        try {
            rsaPublic = StringUtils.replace(rsaPublic, "-----BEGIN PRIVATE KEY-----", "");
            rsaPublic = StringUtils.replace(rsaPublic, "-----END PRIVATE KEY-----", "");
            return doVerify(presign + paramsToStr(params), sign, rsaPublic);
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * Verifies the signature
     *
     * @param content
     * @param sign
     * @param publicKey
     * @return
     */
    public static boolean doVerify(String content, String sign, String publicKey) {
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            byte[] encodedKey = Base64.decodeBase64(publicKey);
            PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));

            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
            signature.initVerify(pubKey);
            signature.update(content.getBytes(StandardCharsets.UTF_8));

            return signature.verify(Base64.decodeBase64(sign));
        } catch (Exception ex) {
            LOG.error("验签失败,content={}", content, ex);
            throw new IllegalArgumentException("rsa verify fail");
        }
    }

    /**
     * Converts parameters into ordered strings
     *
     * @param params
     * @return
     */
    private static String paramsToStr(Map<String, String> params) {
        StringBuilder param = new StringBuilder();
        List<String> keys = new ArrayList(params.keySet());
        // Sorts the specified keys
        Collections.sort(keys);
        int index = 0;
        Iterator<String> iterator = keys.iterator();
        while (iterator.hasNext()) {
            String key = iterator.next();
            String value = params.get(key);
            // Filter out null and empty values
            if ("x-fp-signature".equals(key) || "signature".equals(key) || "sign".equals(key) || StringUtils.isBlank(value)) {
                continue;
            }
            param.append(index == 0 ? "" : "&").append(key).append("=").append(value);
            index++;
        }
        return param.toString();
    }

    /**
     * Returns URI
     *
     * @param url
     * @return
     */
    public static URI getURI(String url) {
        if (!(StringUtils.startsWithIgnoreCase(url, "http://") || StringUtils
                .startsWithIgnoreCase(url, "https://"))) {
            url = "http://" + url;
        }
        try {
            URI uri = new URI(url);
            return uri;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    // ******************** WEBHOOK DEMO START ********************//
    @PostMapping("/webhook_sign_verify")
    public String webhookSignVerify(@RequestBody Map<String, String> requestBody, HttpServletRequest request) {
        String signature = request.getHeader("X-FP-Signature");

        // Converts header keys to lower case
        Map<String, String> headers = new HashMap<>();
        headers.put("x-fp-timestamp", request.getHeader("X-FP-Timestamp"));
        headers.put("x-fp-nonce", request.getHeader("X-FP-Nonce"));
        headers.put("x-fp-partner-id", request.getHeader("X-FP-Partner-Id"));

        Map<String, String> params = new HashMap<>();
        params.putAll(requestBody);
        params.putAll(headers);

        String url = request.getRequestURL().toString();
        URI uri = SignUtil.getURI(url);
        String presign = request.getMethod() + uri.getHost() + request.getRequestURI() + "?";
        Boolean verified = false;
        try {
            verified = SignUtil.rsaVerify(params, FATPAY_PUBLIC_KEY, presign, signature);
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (!verified) {
            return "Signature error";
        }
        // do something
        return "success";
    }
    // ******************** WEBHOOK DEMO END ********************//
}
const crypto = require('crypto');

var text = "original text to be signed"
var publickey = "public key to verify sign"

// verify signature
var verifier = crypto.createVerify("RSA-SHA256");
verifier.update(text);
result = verifier.verify(publickey, signature, "base64");
console.log("verify result: " + result)
Webhook 订单回调验签