Appearance
开始
UCC-PAY是领先的支付解决方案,提供支付、查询等功能。
HONGKONG支付API地址
API接口请求
必须采用application/json格式进行请求,统一采用POST,接口需要拼接验签POST参数
API返回格式
code=200表示请求成功,其它状态码均表示失败,如有返回的数据均在data参数中
{"code":200,"message":"返回的信息","data":{}}公共验签POST参数
| 参数 | 说明 |
|---|---|
| key | APIKEY |
| time | 接口调用时间戳(UTC+8),如果时间戳偏差超过60秒,则无法访问 |
| nonce_str | 随机数,至少8位 |
| sign | 签名 |
接口验签
签名方式,所有POST参数包含time、nonce_str、key进行ksort排列,排序好的参数加上secret,如nonceStr=2&time=3&key=4secret,然后进行32位MD5加密,最后get参数为:nonce_str=2&time=3&key=4&sign=xxxx
PHP DEMO
php
<?php
class Pay
{
public function run()
{
$domain = 'https://xxxxxxx';
//以获取接口主体信息为例,生成接口访问URL
$key = 'xxxxx';
$secret = 'xxxxx';
$data = [];
$data['key'] = $key;
// 获取主体信息
// $params = $this->encodeUrlParam($secret, $data);
// $resp = $this->post($domain.'/externalApi/v1/company/get-info', $params);
// echo $resp;
// 支付请求
$data['order_sn'] = "OT00001";
$data['body'] = "测试01";
$data['amount'] = 0.01;
$data['notify_url'] = '回调通知url';
$data['return_url'] = '支付完成跳转url';
$params = $this->encodeUrlParam($secret, $data);
$resp = $this->post($domain . '/externalApi/v1/pay/all-qrcode-pay', $params);
echo $resp;
}
/**
* 发送请求
*
* @param string $url
* @param array $params
* @return bool|string
* @throws Exception
*/
protected function post(string $url, array $params): bool|string
{
$json = json_encode($params, 320);
$headers = [
'Content-Type: application/json; charset=utf-8',
];
$ch = curl_init();//初始化curl
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_DNS_USE_GLOBAL_CACHE, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($ch);
$err = curl_error($ch);
$errno = curl_errno($ch);
if ($errno) {
$msg = 'curl errInfo: ' . $err . ' curl errNo: ' . $errno;
throw new \Exception($msg);
}
curl_close($ch);
return $data;
}
/**
* 生成认证链接
* @param string $secret secret
* @param array $data 需要提交的数据,包含接口提供的key
* @param string $signName 接口需要认证加密的参数值,默认为sign
* @return mixed
*/
protected function encodeUrlParam(string $secret, array $data = [], string $signName = 'sign'): mixed
{
if (isset($data[$signName])) {
unset($data[$signName]);
}
$data['time'] = time();
$data['nonce_str'] = $this->random(16);
$params = $this->sortParams($data);
$params .= $secret;
$data[$signName] = strtolower(md5($params));
return $data;
}
/**
* 参数排序
* @param array $params
* @return string
*/
protected function sortParams(array $params): string
{
ksort($params);
$buff = "";
foreach ($params as $k => $v) {
if ($v != "" && !is_array($v)) {
$buff .= $k . "=" . urlencode($v) . "&";
}
}
return trim($buff, "&");
}
/**
* 生成随机值
* @param int $length
* @param bool $numeric
* @return string
*/
protected function random(int $length, bool $numeric = false): string
{
$seed = base_convert(md5(microtime() . $_SERVER['DOCUMENT_ROOT']), 16, $numeric ? 10 : 35);
$seed = $numeric ? (str_replace('0', '', $seed) . '012340567890') : ($seed . 'zZ' . strtoupper($seed));
$hash = '';
if (!$numeric) {
$hash = chr(rand(1, 26) + rand(0, 1) * 32 + 64);
$length--;
}
$max = strlen($seed) - 1;
$seed = str_split($seed);
for ($i = 0; $i < $length; $i++) {
$hash .= $seed[mt_rand(0, $max)];
}
return $hash;
}
}
$pay = new Pay();
$pay->run();JAVA DEMO
java
import com.alibaba.fastjson.JSONObject;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.client.RestTemplate;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
public class UrlParamEncoder {
// 生成认证链接
public Map<String, String> encodeUrlParam(String secret, Map<String, String> data, String signName) {
if (data.containsKey(signName)) {
data.remove(signName);
}
// 添加时间戳和随机数
data.put("time", String.valueOf(System.currentTimeMillis() / 1000)); // 时间戳
data.put("nonce_str", random(16)); // 随机字符串
// 排序并生成签名
String params = sortParams(data) + secret;
data.put(signName, md5(params).toLowerCase());
return data;
}
// 参数排序
public String sortParams(Map<String, String> params) {
return params.entrySet().stream()
.filter(entry -> !entry.getValue().isEmpty() && !(entry.getValue() instanceof String && entry.getValue().equals("")))
.sorted(Map.Entry.comparingByKey())
.map(entry -> entry.getKey() + "=" + encode(entry.getValue()))
.collect(Collectors.joining("&"));
}
// MD5 加密
public String md5(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hashBytes = md.digest(input.getBytes());
StringBuilder hexString = new StringBuilder();
for (byte b : hashBytes) {
hexString.append(String.format("%02x", b));
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
// URL 编码
public String encode(String value) {
try {
return java.net.URLEncoder.encode(value, "UTF-8");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// 生成随机字符串
public String random(int length) {
return random(length, false);
}
public String random(int length, boolean numeric) {
String seed = numeric ? "0123456789" : "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
StringBuilder hash = new StringBuilder();
for (int i = 0; i < length; i++) {
int index = (int) (Math.random() * seed.length());
hash.append(seed.charAt(index));
}
return hash.toString();
}
public static void main(String[] args) {
UrlParamEncoder encoder = new UrlParamEncoder();
String url = "https://xxxxx/externalApi/v1/company/get-info";
String key = "xxxxx";
String secret = "xxxxx";
// 加密参数
Map<String, String> data = new HashMap<>();
data.put("key", key);
data = encoder.encodeUrlParam(secret, data, "sign");
JSONObject params = (JSONObject) JSONObject.toJSON(data);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.postForObject(url, new HttpEntity<>(params.toString(), headers), String.class);
System.out.println("API Resp: " + result);
}
}