# 集成 FaTPay 页面加签

本文是[集成 FaTPay 页面加签](/zh/reference/integration-tutorial/widget-signature.md#url-jie-kou-jia-qian) 的 demo

{% hint style="info" %}
使用本文代码时，请务必将其中的合作伙伴账号相关信息替换为您自身的
{% endhint %}

{% tabs %}
{% tab title="Java" %}
{% code lineNumbers="true" %}

```java
package onramp.widgetsign;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.*;
import java.util.*;

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

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

    /**
     * secretKey
     */
    private static final String SECRET_KEY = "<YOUR SECRET KEY>";

    /**
     * partnerId
     */
    private static final String PARTNERID = "<YOUR PARTNER ID>";

    /**
     * walletAddress
     */
    private static final String WALLETADDRESS = "<YOUR WALLET ADDRESS>";

    /**
     * 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();
    }

    /**
     * Generates the HmacSHA256 signature
     *
     * @param secretKey
     * @param params
     * @return
     * @throws InvalidKeyException
     * @throws NoSuchAlgorithmException
     * @throws UnsupportedEncodingException
     */
    public static String generateSignature(String secretKey, Map<String, String> params) throws InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException {
        String signature = "";
        if (StringUtils.isBlank(params.get("partnerId")) || StringUtils.isBlank(params.get("walletAddress")) || StringUtils.isBlank(params.get("timestamp")) || StringUtils.isBlank(params.get("nonce")) || StringUtils.isBlank(secretKey)) {
            return signature;
        }
        String baseParamString = paramsToStr(params);

        Mac sha256Mac = Mac.getInstance("HmacSHA256");
        sha256Mac.init(new SecretKeySpec(secretKey.getBytes(), "HmacSHA256"));
        byte[] bytes = sha256Mac.doFinal(baseParamString.getBytes());
        signature = Base64.encodeBase64String(bytes);
        signature = urlEncode(signature);
        LOG.info("base:{} secretKey:{} sha256:{} base64:{}", baseParamString, secretKey, bytes.toString(), signature);
        return signature;
    }

    /**
     * urlEncode
     *
     * @param string
     * @return
     * @throws UnsupportedEncodingException
     */
    private static String urlEncode(String string) throws UnsupportedEncodingException {
        String encoded = URLEncoder.encode(string, "UTF-8").replace("+", "%20");
        return encoded;
    }

    // ******************** WIDGET SIGNATURE DEMO START ********************//
    public static void widgetDemo() {
        // Parameters to be signed
        Map<String, String> shaParamMap = new HashMap<>();
        shaParamMap.put("timestamp", "1661425554");
        shaParamMap.put("nonce", "166142");
        shaParamMap.put("partnerId", PARTNERID);
        shaParamMap.put("walletAddress", WALLETADDRESS);
        shaParamMap.put("walletAddressLocked", "1");
        shaParamMap.put("walletAddressHidden", "1");
        shaParamMap.put("ext", "ext");

        String hmacSHA256 = "";
        try {
            hmacSHA256 = SignUtil.generateSignature(SECRET_KEY, shaParamMap);
        } catch (Exception e) {
            LOG.error("sign error, exception:{}", e);
        }
        LOG.info(hmacSHA256);
    }
    // ******************** WIDGET SIGNATURE DEMO END ********************//
}


```

{% endcode %}
{% endtab %}

{% tab title="Node.js" %}
{% code lineNumbers="true" %}

```java
const crypto = require('crypto');

var text = "original text to be signed";
var secretkey = "private key to generate sign";

// generate signature
var signature = crypto.createHmac('sha256', secretkey).update(text).digest("base64");
console.info("signature: " + signature);
```

{% endcode %}
{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://dev.fatpay.org/zh/appendix/demo/widget-signature-demo.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
