接口地址
https://vmshell.win/api/v1/pay.phphttps://vmshell.win/api/v1/query.phphttps://vmshell.win/api/sandbox/test_pay.phphttps://vmshell.win/api/sandbox/query.php商户只需对接统一 API,即可创建 HKD 订单、选择支付方式、获取收银台或二维码、接收支付结果回调,并在后台核对交易流水、退款和钱包入账。
https://vmshell.win/api/v1/pay.phphttps://vmshell.win/api/v1/query.phphttps://vmshell.win/api/sandbox/test_pay.phphttps://vmshell.win/api/sandbox/query.php| 字段 | 必填 | 格式 | 说明 |
|---|---|---|---|
app_id | 是 | 字符串 | 应用 AppId,来自“我的应用”。 |
method | 是 | alipay_hk / alipay_cn / wechat | 指定支付方式。也可让用户在收银台选择。 |
order_id | 是 | 唯一字符串 | 商户系统订单号,同一应用下不可重复。 |
amount | 是 | decimal(10,2) | 订单金额,固定 HKD;三个正式网关默认单笔范围为 5.00 - 500000.00 HKD,后台可在支付网关中心调整。 |
currency | 是 | HKD | 当前正式商用统一为 HKD。 |
customer_email | 是 | 付款用户邮箱,用于交易流水、争议、退款和售后查询。 | |
subject | 建议 | 字符串 | 商品标题,会进入订单记录。 |
body | 否 | 字符串 | 商品描述。 |
remark | 否 | 字符串 | 付款备注;未传时系统可使用默认备注。 |
notify_url | 是 | HTTPS URL | 平台异步通知商户的回调地址。 |
return_url | 建议 | HTTPS URL | 用户支付后返回商户页面。 |
sign_type | 是 | HMAC-SHA256 | 新应用默认 HMAC-SHA256;旧应用可由后台切换 MD5 兼容。 |
timestamp | 是 | Unix 秒 | 安全模式默认 300 秒有效期,超时拒绝。 |
nonce | 是 | 随机字符串 | 同一 AppId + endpoint + nonce 在有效期内只能使用一次,防重放。 |
encrypted_data | 可选 | AES-256-GCM | 敏感字段加密载荷;同时传 iv 和 tag。notify_url 保持明文。 |
direct | 否 | 0/1 | 传 1 时尽量直接返回二维码/支付链接,适合商户自有收银台。 |
signature | 是 | HMAC | 按签名规则计算。 |
下游商户可以继续使用统一下单接口 /api/v1/pay.php。平台会先按网关配置校验单笔金额,默认最低 5.00 HKD、最高 500000.00 HKD;通过后再根据 terminal 与 payment_scene 自动选择二维码、支付宝 WAP/WEB 或微信 H5。上游接口地址与签名规则不变,变化的是平台内部提交给支付网络的 wayCode。
| 场景 | payment_method | terminal | payment_scene | 平台处理 |
|---|---|---|---|---|
| 电脑支付宝二维码 | alipay_hk / alipay_cn | pc | qr | 返回 payment_mode=qr,展示 qr_code_url 或 qr_content。 |
| 手机支付宝唤起 | alipay_hk / alipay_cn | mobile | wap 或 web | 返回 payment_mode=redirect,手机浏览器跳转 payment_url。 |
| 电脑微信二维码 | wechat_pay | pc | qr | 返回二维码内容,适合电脑网页展示。 |
| 手机微信 H5 | wechat_pay | mobile | h5 | 返回 H5 支付链接,手机端跳转唤起微信支付。 |
可选参数:terminal=auto|pc|mobile,payment_scene=auto|qr|wap|web|h5,wayCode 可用于联调时手动覆盖,paymentInst=ALIPAYHK|ALIPAYCN 可用于支付宝 HKD 场景。
{
"app_id": "vmp_xxx",
"payment_method": "alipay_cn",
"terminal": "mobile",
"payment_scene": "wap",
"direct": "1",
"order_id": "MCH202606150001",
"amount": "5.00",
"currency": "HKD",
"customer_email": "buyer@example.com",
"notify_url": "https://merchant.example.com/notify.php",
"return_url": "https://merchant.example.com/return.php",
"timestamp": "1780000000",
"nonce": "random_nonce",
"sign_type": "HMAC-SHA256",
"signature": "..."
}返回时重点判断:payment_mode=qr 展示二维码;payment_mode=redirect 时,手机端优先跳转 mobile_h5_url,其次才使用 payment_url。新增返回字段包括 terminal、payment_scene、way_code、if_code。
| 字段 | 说明 | 下游处理 |
|---|---|---|
mobile_h5_url | VmShellPAY 封装的手机 H5 支付页,格式为 /pages/mobile_h5_pay.php?session_id=...。 | 手机端直接打开该地址,由平台页面负责唤起支付宝/微信 App、轮询支付状态并返回 return_url。 |
payment_url | 支付入口地址。手机 H5/WAP 场景下通常等同于 mobile_h5_url;PC 二维码场景下可为支付链接。 | 根据 payment_mode 判断:redirect 跳转,qr 展示二维码。 |
checkout_url | 平台收银台地址,格式一般为 /pages/checkout.php?session_id=...。 | 适合 PC 收银台展示或平台统一收银台模式;移动端不建议直接把它当作 App 唤起链接。 |
payment_mode | qr 或 redirect。 | qr 展示 qr_code_url;redirect 优先打开 mobile_h5_url,没有时再退回 payment_url。 |
移动 H5 封装后,下游不需要接触上游 H5 地址。支付宝手机用 terminal=mobile&payment_scene=wap,微信手机用 terminal=mobile&payment_scene=h5,平台统一返回 mobile_h5_url。浏览器最终跳回 return_url 只用于体验展示,订单是否真正成功仍以 notify_url 或查单结果为准。
移除空值、数组、signature 与 sign 字段,按参数名 ASCII 升序拼接为 key=value&key=value。新商户默认用 AppSecret 做 HMAC-SHA256;兼容 MD5 时才追加 &key=APP_SECRET 后取 MD5。
amount=10.00&app_id=vmp_xxx¤cy=HKD&method=alipay_hk&nonce=8f8b...&order_id=ORDER10001&sign_type=HMAC-SHA256×tamp=1781160000
signature=hash_hmac('sha256', canonical_string, APP_SECRET)启用 AES-256-GCM 后,customer_email、customer_name、customer_phone、subject、body、remark、ext_param 等敏感字段放入 encrypted_data;notify_url、订单号、金额、币种、支付方式保持明文,便于路由、风控和回调。
| 字段 | 说明 |
|---|---|
app_id | 应用 AppId。 |
order_id | 商户订单号。 |
transaction_id | 平台交易号。 |
amount / currency | 订单金额和币种。 |
status | paid、failed、refunded、partial_refund 等。 |
customer_email | 付款用户邮箱。 |
merchant_net_amount | 商户净入账金额。 |
refund_id / refund_amount | 退款事件时返回。 |
timestamp / nonce / signature | 回调时间、防重放随机串和平台签名。 |
encrypted_data / iv / tag | 应用启用加密时,敏感回调字段会进入 AES-256-GCM 加密载荷。 |
{
"status": "success",
"session_id": "vmp_sess_xxx",
"transaction_id": "VMP20260611123456ABCD",
"order_id": "ORDER10001",
"amount": "10.00",
"currency": "HKD",
"pay_url": "https://vmshell.win/pages/checkout.php?session_id=vmp_sess_xxx",
"merchant_net_amount": "9.45"
}服务器端 POST 到统一网关,建议传 direct=1,商户页面即可直接显示平台返回的二维码或支付链接。
$params = [
'app_id' => 'vmp_xxx',
'method' => 'alipay_cn',
'order_id' => 'ORDER' . date('YmdHis'),
'amount' => '10.00',
'currency' => 'HKD',
'customer_email' => 'buyer@example.com',
'subject' => 'VmShell PAY Order',
'notify_url' => 'https://merchant.example.com/notify.php',
'return_url' => 'https://merchant.example.com/return.php',
'sign_type' => 'HMAC-SHA256',
'timestamp' => time(),
'nonce' => bin2hex(random_bytes(12)),
'direct' => '1',
];
$params['signature'] = vmp_sign($params, $appSecret);
$response = http_post_json('https://vmshell.win/api/v1/pay.php', $params);| 接口 | 方法 | 必填参数 | 用途 |
|---|---|---|---|
/api/v1/query.php | GET/POST | app_id, order_id 或 transaction_id, sign_type, timestamp, nonce, signature | 查询平台订单状态、上游单号、买家邮箱、退款状态和商户回调状态。 |
/api/v1/refund.php | POST | app_id, order_id 或 transaction_id, refund_amount, refund_id, reason, sign_type, timestamp, nonce, signature | 发起全额或部分退款。退款金额不能超过可退金额,商户余额不足时会拒绝。 |
// 查单
$query = ['app_id'=>$appId, 'order_id'=>'ORDER10001', 'sign_type'=>'HMAC-SHA256', 'timestamp'=>time(), 'nonce'=>bin2hex(random_bytes(12))];
$query['signature'] = vmp_sign($query, $appSecret);
// 退款
$refund = [
'app_id'=>$appId,
'order_id'=>'ORDER10001',
'refund_amount'=>'3.00',
'refund_order_id'=>'RF' . date('YmdHis'),
'reason'=>'customer request',
'sign_type'=>'HMAC-SHA256',
'timestamp'=>time(),
'nonce'=>bin2hex(random_bytes(12)),
];
$refund['signature'] = vmp_sign($refund, $appSecret);支付、退款、争议通知都使用同一套签名规则。商户收到回调后必须先验签,再按 order_id 或 transaction_id 幂等处理,成功后输出 success。
function vmp_sign(array $params, string $secret): string {
unset($params['signature'], $params['sign']);
ksort($params);
$pairs = [];
foreach ($params as $key => $value) {
if ($value === '' || $value === null) continue;
$pairs[] = $key . '=' . $value;
}
$canonical = implode('&', $pairs);
$signType = strtoupper($params['sign_type'] ?? 'HMAC-SHA256');
return $signType === 'MD5'
? strtolower(md5($canonical . '&key=' . $secret))
: strtolower(hash_hmac('sha256', $canonical, $secret));
}
$payload = $_POST ?: json_decode(file_get_contents('php://input'), true);
$signature = $payload['signature'] ?? '';
if (!hash_equals($signature, vmp_sign($payload, $appSecret))) {
http_response_code(403);
exit('invalid signature');
}
// TODO: 更新商户本地订单,注意幂等
echo 'success';| HTTP/状态 | message | 处理建议 |
|---|---|---|
400 | AMOUNT_OUT_OF_RANGE / missing required parameter | 检查必填字段、金额格式、币种必须为 HKD;单笔金额需在当前网关配置范围内,默认 5.00 - 500000.00 HKD。 |
401 | invalid signature | 按 ASCII 字典序重新计算签名,确认 AppSecret 正确。 |
403 | Unauthorized IP address | 后台应用 IP 白名单需包含商户服务器出口 IP。 |
403 | Application is still in sandbox | 应用还未审批为正式商用,请提交沙箱报告后等待后台通过。 |
409 | duplicate order_id | 同一 AppId 下订单号必须唯一。 |
402/422 | insufficient merchant balance | 退款金额和退款手续费超过商户可用余额。 |
502 | gateway failed | 上游通道异常,商户可稍后重试或联系平台客服。 |
modules/gateways/,在后台启用 VmShell PAY,填写 AppId、AppSecret、notify_url、return_url,货币固定 HKD。下游商户始终只调用 /api/v1/pay.php。PC 场景返回二维码;手机 H5/WAP 场景返回 VmShellPAY 封装地址 mobile_h5_url,由 /pages/mobile_h5_pay.php 负责唤起支付宝/微信 App、轮询订单结果并返回商户 return_url。
| 场景 | 必传/建议参数 | 核心返回 | 下游动作 |
|---|---|---|---|
| PC 支付宝/微信扫码 | terminal=pcpayment_scene=qrdirect=1 | payment_mode=qrqr_code_url | 展示二维码,等待异步通知或查单。 |
| 手机支付宝 H5/WAP | payment_method=alipay_cn/alipay_hkterminal=mobilepayment_scene=wap | payment_mode=redirectmobile_h5_url | 跳转 mobile_h5_url。 |
| 手机微信 H5 | payment_method=wechat_payterminal=mobilepayment_scene=h5 | payment_mode=redirectmobile_h5_url | 跳转 mobile_h5_url。 |