系统使用md5签名,秘钥请登录商户后台获取
系统统一使用POST请求,发送JSON格式参数。 API域名请联系客服获取
{
"sign": "72550F03C5DA4BD6666666666F75",
"signtype": "MD5",
"transdata": {
"country_code": "BD",
"merchant_code": "M2512166666666666",
"notify_url": "<http://xxx.com>",
"order_amount": "470",
"order_no": "33333333333",
"pay_type": "bkash"
}
}
参数遵循上述格式,sign放置签名
将transdata所有非空字段按ASCII码排序,以 key=value 形式用&(与符号)连接起来,最后拼上&key=${key},进行md5签名,并把签名转大写。
• 验签参数应支持动态变化,正确的做法是获取所有请求或返回参数进行验签,而非固定获取文档中列出的参数,以确保参数的调整不会影响接口使用(验签方式规则不变,验签参数可能会变化)。
排序示例:
merchant_code=test1111¬ify_url=1&order_amount=50&order_no=541445444144414&order_time=20201102081725&pay_type=india-upi&product_code=test001&product_name=ttt001&return_url=1&user_no=51070173&key=dsfkgjslgfkslfda
使用sign方法即可
package com.cowpay.demo.utils;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Arrays;
/**
* Md5加密方法
*
* @author cowpay
*/
public class Md5Utils
{
private static final Logger log = LoggerFactory.getLogger(Md5Utils.class);
private static byte[] md5(String s)
{
MessageDigest algorithm;
try
{
algorithm = MessageDigest.getInstance("MD5");
algorithm.reset();
algorithm.update(s.getBytes("UTF-8"));
byte[] messageDigest = algorithm.digest();
return messageDigest;
}
catch (Exception e)
{
log.error("MD5 Error...", e);
}
return null;
}
private static final String toHex(byte hash[])
{
if (hash == null)
{
return null;
}
StringBuffer buf = new StringBuffer(hash.length * 2);
int i;
for (i = 0; i < hash.length; i++)
{
if ((hash[i] & 0xff) < 0x10)
{
buf.append("0");
}
buf.append(Long.toString(hash[i] & 0xff, 16));
}
return buf.toString();
}
public static String hash(String s)
{
try
{
return new String(toHex(md5(s)).getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8);
}
catch (Exception e)
{
log.error("not supported charset...{}", e);
return s;
}
}
/**
* 把json对象安装ASCll码排序,跳过为空的属性
*
* @param object
* @return {@link String}
*/
public static String sortByASCll(JSONObject object) {
String[] sortedKeys = (String[]) object.keySet().toArray((Object[]) new String[0]);
Arrays.sort(sortedKeys);
StringBuilder sb = new StringBuilder();
byte b;
int i;
String[] arrayOfString1;
for (i = (arrayOfString1 = sortedKeys).length, b = 0; b < i;) {
String key = arrayOfString1[b];
if (!"sign".equals(key)) {
if (object.get(key) != null && !StringUtils.isBlank(object.get(key).toString()))
sb.append(key).append("=").append(object.get(key).toString()).append("&");
}
b++;
}
sb.deleteCharAt(sb.length() - 1);
return sb.toString();
}
/**
* 排序并hash
*
* @param object
* @param secretKey
* @return {@link String}
*/
public static String sign(JSONObject object, String secretKey) {
String waitSignStr = sortByASCll(object) + "&key=" + secretKey;
log.info("待签名参数:{}", waitSignStr);
String hash = hash(waitSignStr);
log.info("签名结果:{}", hash);
return hash;
}
}