1. 交易通知及对账
星驿支付文档中心
  • 文档说明
    • 阅读对象
    • 版本说明
  • 术语
    • 支付模式
    • 名词解释
    • 支付产品
      • 付款码支付
      • 聚合码支付
      • PC支付
      • 小程序支付
        • 微信小程序支付
        • 支付宝小程序支付
      • APP支付
        • 微信支付
        • 支付宝支付
      • H5支付
        • 微信H5支付
        • 支付宝H5支付
        • 云闪付H5支付
        • 手机浏览器H5支付
      • Native支付
        • 支付宝支付
        • 云闪付支付
      • 终端支付
        • 智能云MIS
        • 智能APP
  • 接口规则
    • 协议规则
    • 安全规范
  • 支付交易
    • 交易前指引
      • 微信认证操作流程
      • 支付宝认证操作流程
      • H5页面微信支付对接前准备
      • H5页面支付宝支付对接前准备
      • 支付流程
      • 支付接入注意事项
      • 消费者IP获取指引
    • 基础支付
      • 付款码支付
      • JSAPI支付
      • 订单查询
      • 扫码支付-星驿码
      • 扫码支付-官方码
      • 扫码支付-场景码
      • 关闭订单
      • 撤销订单
      • 退款
      • 退款查询
      • 授权码查询openid
      • 获取银联用户标识
      • 获取微信刷脸凭证
      • 成品油(现金/储值)开票
    • 小程序支付
      • 使用说明
      • 小程序半屏-星驿付
      • 小程序半屏-场景
    • 扫码预授权
      • 扫码预授权
      • 预授权查询
      • 预授权撤销
      • 预授权撤销查询
      • 预授权完成
      • 预授权完成查询
      • 预授权完成撤销
      • 预授权完成撤销查询
    • 订单推送
      • 推送终端交易
      • 关闭推送终端交易
      • 碰一下推单状态查询
      • 碰一下订单取消
      • 碰一下订单推送
    • 智能终端SDK
      • 智能终端SDK
    • 交易通知及对账
      • 交易对账文件-场景应用
        GET
      • 交易对账文件-ISV
        GET
      • 交易和退款结果通知
        POST
      • 交易手续费通知
        POST
    • 刷卡预授权
      • 预授权撤销
      • 预授权完成撤销
  • 商户管理
    • 前件前指引
      • 进件说明
      • 图片示例
      • 微信认证操作流程
      • 支付宝认证操作流程
      • 附件下载
    • 商户入网
      • 商户进件上传图片
      • 普通商户进件
      • 普通商户信息修改
      • 小微商户进件
      • 小微商户信息修改
      • 审核结果查询
      • 商户审核结果通知
      • 待审核商户撤回
      • 商户信息查询
      • 结算卡修改
      • 商户快捷修改
      • 受益人信息查询
      • 商户报备查询
      • 商户报备结果通知
      • 商户状态修改
      • 终端报备查询
      • 商户阶梯费率配置
      • 商户阶梯费率查询
    • 商户协议签约
      • 入网协议签约接口调用流程
      • 普通商户用户开户
      • 小微商户用户开户
      • 发短信验证码
      • 获取签约链接
      • 校验验证码
      • 校验验证码-补签
      • 签约结果通知
    • 微信支付宝认证
      • 微信申请单提交
      • 微信申请单撤销
      • 微信申请单状态查询
      • 微信商户授权状态查询
      • 支付宝申请单提交
      • 支付宝申请单撤销
      • 支付宝申请单状态查询
      • 支付宝商户授权状态查询
    • 微信开发配置
      • 微信APPID配置
      • 微信支付目录配置
      • 微信公众号查询
      • 微信开发配置查询
      • 指定渠道报备
      • 微信小程序冻结状态查询
      • 微信小程序冻结通知(非接口)
    • 商户限额调整
      • 商户限额查询
      • 商户提额申请
      • 商户提额记录查询
    • 商户风险处置
      • 商户风险处置通知
      • 风险商户图片上传
      • 微信官方风险商户文件
      • 支付宝官方风险商户文件
      • 风险商户异常流水查询
      • 风险商户调查列表
      • 风险商户调查详情
      • 风险调查单历史查询
      • 风险调查材料下载
      • 风险调查单处理
    • 商户手续费开票
      • 开具发票
      • 开票详情
      • 待开发票信息查询
      • 合并开票商户信息查询
      • 电子普票重发邮箱
      • 开票历史查询
    • 无界收款
      • 无界收款图片上传
      • 无界收款开通
      • 无界收款审核查询
      • 无界收款审核结果通知
  • 资金结算
    • D0结算业务
      • 产品介绍
      • 获取人脸识别链接
      • 人脸认证结果查询
      • D0开通
      • D0信息修改
      • D0状态查询
      • D0开通失败申诉
      • D0申诉结果查询
      • D0申诉结果通知
    • 特殊结算业务
      • 产品介绍
      • 结算业务申请
      • 结算业务变更
      • 结算业务结果查询
      • 结算业务结果通知
    • 提现查账
      • 手工提现
      • 到账记录查询
      • 到账记录批量查询
      • 秒到提现记录查询
      • 账户余额查询
      • 挂账记录查询
      • 补付申请
      • 提现结果通知
      • 账户余额变动通知
      • 提现对账文件
      • 批量结算提现通知
      • 到账附言配置
      • 查询到账附言
  • 星账云管家
    • 星账云管家
    • 功能开通
      • 功能开通(XZY001)
      • 编辑(XZY003)
      • 编辑上传付款凭证(XZY002)
      • 修改生效状态(XZY004)
      • 查询详情信息(XZY005)
      • 产品开通审核通知(XZY006)
    • 公共接口
      • 上传文件(XZY013)
    • 分账
      • 交易
        • 分账结算电子回单下载(XZY037)
        • 余额查询接口(XZY041)
        • 分账合并入账电子回单下载(XZY039)
        • 订单查询(XZY015)
        • 分账(XZY014)
        • 分账撤销退回(XZY017)
        • 分账结果回调(XZY016)
      • 客户管理
        • 新增客户(XZY018)
        • 分账授权申请接口-收单统一结算(XZY043)
        • 批量分账授权申请接口-收单统一结算(XZY044)
        • 合作状态调整(XZY020)
        • 解约/重启签约(XZY-001-002)
        • 编辑客户(XZY023)
        • 替换客户结算卡(XZY022)
        • 审核通知(XZY019)
        • 查询分账客户信息(XZY021)
    • 归集
      • 开户/授权
        • 归集授权申请接口-收单统一结算(XZY037)
        • 审核通知(XZY025)
        • 合作状态调整(XZY026)
        • 查询归集客户信息(XZY027)
        • 替换结算卡(XZY028)
        • 编辑信息(XZY029)
      • 交易
        • 归集合并入账电子回单下载(XZY040)
        • 归集结算电子回单下载(XZY038)
        • 余额查询接口(XZY042)
        • 订单查询(XZY031)
        • 归集-支持自定义服务费(XZY030)
        • 归集(XZY030)
        • 归集结果回调(XZY032)
        • 归集撤销退回(XZY033)
    • 提现
      • 提现订单查询(XZY035)
      • 结算回调通知(XZY050)
      • 提现电子回单下载(XZY040)
      • 提现(XZY036)
    • 账户
      • 结算资金流水查询(XZY047)
      • 结算卡资金流水查询(XZY049)
  • 设备管理与推送
    • 设备管理
      • 收款设备绑定
      • 收款设备解绑
      • 收款设备绑定查询
      • 设备绑定/解绑结果通知
      • 音箱绑定
      • 音箱绑定查询
      • 音箱解绑
    • 设备推送
      • 音箱播报
      • 交易打印
  • 营销活动
    • 银行活动
      • 产品介绍
      • 图片上传
      • 商户补贴列表查询
      • 银行活动报名
      • 银行活动报名结果查询
      • 银行活动报名结果通知
      • 银行活动列表查询
      • 银行活动退出
    • 特殊行业活动
      • 产品介绍
      • 特殊行业活动报名申请
      • 特殊活动报名结果通知
      • 特殊行业商户活动查询
      • 特殊行业活动图片上传
    • 综合账户
      • 营销增资-订单
      • 营销增资-金额
      • 营销增资查询
      • 综合账户余额查询
      • 综合账户流水查询
    • 增值服务
      • 获取增值营销产品列表
      • 获取增值营销产品明细
      • 获取分享链接
      • 推广结果列表查询
      • 推广结果详情
  • 慧徕店开放平台
    • 慧+SPI
      • 对接前准备
      • 商户同步
        • 开发配置
          • 请求域名
          • 加签&验签
        • 商户同步
        • 商户同步查询
        • 商户同步回调
      • 应用模块
        • 产品介绍
        • 开发配置
          • 请求域名
          • 加签&验签
        • 应用及增值服务查询
        • 商户应用注册及增值服务状态查询
        • 应用注册
        • 应用注册状态查询
        • 应用注册回调通知
        • 增值服务激活
        • 增值服务激活状态查询
        • 增值服务激活回调通知
      • 聚合支付SPI
        • 产品介绍
        • 开发配置
          • 签名方式
          • 验签方式
          • 公共参数
        • 支付API
        • 付款码支付
        • 扫码支付-官方码
        • JSAPI支付
        • 扫码支付-聚合码
        • 获取小程序支付信息
        • 订单查询
        • 交易结果通知
        • 退款
        • 退款查询
        • 关闭订单
        • 获取银联用户标识
    • 应用开发API
      • 验签说明
      • 应用支付
      • 门店信息同步
      • 门店增值服务激活
  • 支付广告
    • 微信小程序广告
    • 支付宝小程序广告
    • 支付宝H5广告
    • SDK资源文件
  • 数据字典
    • MCC
      • 搜索查询二级mcc
      • 获取一级mcc目录
      • 获取二级mcc目录
    • 地区码
      • 获取省
      • 获取市
      • 获取区县
    • 落地银行
      • 落地银行查询
      • 落地银行下级机构查询
    • 银行信息
      • 获取银行省信息-联行号
      • 获取银行市信息-联行号
      • 银行信息查询
      • 查询联行号信息
      • 根据银行卡号获取银行信息
    • 连锁品牌
      • 获取连锁品牌信息
  • 分账服务
    • 订单分账
      • 订单分账
      • 订单分账结果查询
      • 订单分账撤销
      • 订单分账对帐文件
    • 余额分账
      • 余额分账
      • 余额分账结果查询
      • 可分账余额查询
    • 分账配置
      • 分账图片上传
      • 分账商户配置
      • 分账商户配置结果查询
      • 分账商户配置结果通知
      • 分账商户移除
      • 快捷创建资金接收方
      • 修改分账比例与金额
      • 商圈信息查询
  • 数据模型
    • FileHeader
    • FileBody
    • StandardResponse
  1. 交易通知及对账

交易手续费通知

测试环境
https://xyf-server-test.postar.cn
测试环境
https://xyf-server-test.postar.cn
POST
/服务商的异步通知地址

简介#

请注意:邮驿付&星驿付后期会对返回参数保留扩展的权力,扩展方式为新增参数但不会删除参数,请商户在解析邮驿付&星驿付返回参数时要支持邮驿付&星驿付可能扩展参数这种情况。
为提升交易性能及稳定性,我司已经完成了全交易链路的改造升级。我司会优先保障交易链路畅通,因此大部分情况下交易结果将不返回商户实收金额(netrAmt),商户手续费(custFee),改为手续费通知接口进行异步通知手续费,影响范围含:异步通知、扫付款码交易即时响应 以及订单查询接口。为避免常规交易结果未响应手续费时造成业务影响,请接入该通知。
该通知与交易结果通知共用同一个通知地址。回调参数中存在NOTIFY_TYPE并且值为01时即为手续费通知。
常见QA如下:
Q1:如果当下未返回手续费,且没有对接新接口,还有什么地方可以获取手续费?
A1:订单查询接口可以等待支付完成后5s左右再进行查询,一般会有更新后的手续费。
Q2:如何区分当下返回的结果是否异常?
A2:付款码支付/订单查询接口/原交易通知中存在FEE_STATE字段,并且值为01时,返回的手续费结果不一定是正确的,需要接受手续费异步通知。
Q3:异步通知如果区分手续费通知还是交易结果通知?
A3:手续费异步通知会带上NOTIFY_TYPE字段,并且值为01,如果没有该字段或者字段不为01,则是正常的交易结果通知。
Q4:新手续费通知地址是否支持独立配置?
A4:不支持,和原交易通知地址一致。但是联调完成后需要通知运营,否则手续费也不会通知。
返回值必带:{"rspCod":"","rspMsg":"success"},返回的为对象,非字符串。
正向交易成功、反向退款成功都可异步通知(早期机构需要反向退款通知,可联系运营后台配置),如果首次通知失败,则会每隔10s/15s/30s/1m/5m/10m/30m/1h/1h/3h通知一次,共推送10次。
所以在接收成功时,请务必带上"rspMsg":"success",否则平台将一直发送该条通知,直到10次后就不再发送。
由于网络异常、系统波动等原因,可能会存在用户支付成功、但是商户侧未能成功接收到支付结果异步通知的情况。这将会导致商户获取不到支付结果、用户订单显示为未支付,用户体验差且易造成客诉。
为杜绝以上问题,需要商户同时接入支付结果异步通知与订单查询接口。当商户侧未收到支付结果异步通知时,必须调用 /yyfsevr/order/orderQuery(订单查询接口)查询订单的支付结果。

异步返回结果验签#

假设接收到通知的示例如下:
注意:以下示例报文仅供参考,实际返回的详细报文请以实际返回为准。
{"WX_AGET_SUBSIDY":"0","CUST_ID":"60000012628620","AGET_CUST_ID":"61000000582957","MEDIATYPE":"","POS_VOUCHERNO":"hi9njr","THREE_ORDER_NO":"2511042491723721","sign":"YZBvY7CN18RPi6wX/UeAhOO+/5F/zjgVRGbgfUoShnUui3xweD8TxPwT07+rYoz8q9XpsdQ7jTLBibK2rIevb6ojaq5FJcgbZke/IGOIJjLiEviQ7dGiU9xBQ3SUVyPEibxVHlMfzbo7PlxORjF2hvNlSXIB8o8vp0pvXVN99+PGZqyyksi1PDfPDiVJZdZX4uGy+S7//NXGaJTE2669g8FMSRadsc2wdaW/flMjb0kvI8BZhjvZVN8vohaBu1aoCufyUJqwcDtpvR9o5qA9txJQfJdwaddZdvzymJAZkWLmllXr4mzgMyU5bZefGTf8Fu2ydN7h00/PyMC32HxWXg==","CARD_TYPE":"01","OLD_FEE":"0","ORDER_NO":"20251104CChi9njr","ACTUAL_PAY_AMT":"2","T_ORDER_NO":"20251104CChi9njr","AGET_ID":"61000000582957","WX_CUST_SUBSIDY":"0","TERM_FEE":"0","ORDER_STATUS":"1","POS_PAY_WAY":"","CODE_AGE_AMT":"0","DISCOUNT_FEE":"0","BANK_CODE":"CCB_DEBIT","ORD_TYPE":"","SREF_NO":"","PAY_CHANNEL":"2","REFUND_DIS_AMT":"","DISCOUNT_FLAG":"0","LIMIT_FEE":"0","DEBT_STATE":"20251104","PAY_WAY":"8","OLD_TXAMT":"2","TRAN_TYPE_SER":"01","CODE_AMT":"0","TXAMT":"2","SUB_OPEN_ID":"oBY7i5WShNImAoHaKuY6zmu-gAc8","NETR_AMT":"2","OPEN_ID":"oBY7i5WShNImAoHaKuY6zmu-gAc8","MERCH_CONTRIBUTE":"0","CUST_AMT":"0","TRADING_IP":"39.144.92.50","MERCID":"856342004348074","CUST_FEE":"0","USTLDAT":"20251104","T_PAY_NO":"4200002861202511042403075191","ORDER_TIME":"20251104155010","OLD_ORDER_NO":"","BANK_NAME":"建设银行(借记卡)"}
第一步:在通知返回参数列表中,除去 sign 参数外,通知返回的参数均为待验签的参数。
第二步:将剩下参数进行字典排序,组成字符串,得到拼接串:
ACTUAL_PAY_AMT=2&AGET_CUST_ID=61000000582957&AGET_ID=61000000582957&BANK_CODE=CCB_DEBIT&BANK_NAME=建设银行(借记卡)&CARD_TYPE=01&CODE_AGE_AMT=0&CODE_AMT=0&CUST_AMT=0&CUST_FEE=0&CUST_ID=60000012628620&DEBT_STATE=20251104&DISCOUNT_FEE=0&DISCOUNT_FLAG=0&LIMIT_FEE=0&MEDIATYPE=&MERCH_CONTRIBUTE=0&MERCID=856342004348074&NETR_AMT=2&OLD_FEE=0&OLD_ORDER_NO=&OLD_TXAMT=2&OPEN_ID=oBY7i5WShNImAoHaKuY6zmu-gAc8&ORDER_NO=20251104CChi9njr&ORDER_STATUS=1&ORDER_TIME=20251104155010&ORD_TYPE=&PAY_CHANNEL=2&PAY_WAY=8&POS_PAY_WAY=&POS_VOUCHERNO=hi9njr&REFUND_DIS_AMT=&SREF_NO=&SUB_OPEN_ID=oBY7i5WShNImAoHaKuY6zmu-gAc8&TERM_FEE=0&THREE_ORDER_NO=2511042491723721&TRADING_IP=39.144.92.50&TRAN_TYPE_SER=01&TXAMT=2&T_ORDER_NO=20251104CChi9njr&T_PAY_NO=4200002861202511042403075191&USTLDAT=20251104&WX_AGET_SUBSIDY=0&WX_CUST_SUBSIDY=0
第三步:将拼接串使用 SHA256 编码,生成字符串1:
d8727d96bbb4bae07f5caef4d56c6c79b1d3e079c00bb55df8284cadd0351829
第四步:将签名参数(sign)使用 RSA 公钥解密为字符串2。
第五步:将字符串1和字符串2进行比较,相同即为验签通过,反之验签失败。

验签demo#

1.
JAVA
展开查看完整demo
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.ArrayUtils;
import sun.misc.BASE64Decoder;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.TreeMap;


/**
 * 公钥解签
 */
@Log4j2
public class RUtil {
    /**     
     *  验证sign
     *  plainText 返回数据报文
     *  publicKey 公钥
     * @return
     */
    public static boolean checkSign(String plainText,String publicKey) throws Exception {
        TreeMap<String ,Object> map = JSONObject.parseObject(plainText, new TypeReference<TreeMap<String, Object>>(){});
        System.out.println(JSONObject.toJSONString(map));
        StringBuilder sb = new StringBuilder();
        String sign = "";
        for (String key : map.keySet()){
            if("sign".equals(key)){
                sign =(String) map.get(key);
                continue;
            }
            if (map.get(key) != null) {
                sb.append(key).append("=").append(map.get(key)).append("&");
            }  
        }
        String res = sb.substring(0,sb.lastIndexOf("&"));
        log.info("拼接字符串:"+res);
        String sha256 = SHA256.getSHA256(res);
        log.info("拼接串的SHA256:"+sha256);
        String decodeSha256 = decrypt(publicKey,sign);
        log.info("sign解密的SHA256:"+decodeSha256);

        return sha256.equals(decodeSha256);
    }

    /**
     * 公钥解密过程
     *
     * @param key  公钥
     * @param data 密文数据
     * @return 明文
     * @throws Exception 解密过程中的异常信息
     */
    public static String decrypt(String key, String data) throws Exception {
        if (key == null) {
            throw new Exception("解密公钥为空, 请设置");
        }
        PublicKey publicKey = getPublicKey(key);
        byte[] cipherData = Base64Util.decode(data);
        Cipher cipher = null;
        try {
            // 使用默认RSA
            cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, publicKey);

            byte[] buf = (byte[]) null;
            for (int i = 0; i < cipherData.length; i += 256) {
                byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(cipherData, i, i + 256));
                if(buf == null) {
                    buf = doFinal;
                } else {
                    buf = addBytes(buf,doFinal);
                }
            }
            return new String(buf);
        } catch (NoSuchAlgorithmException e) {
            throw new Exception("无此解密算法");
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
            return null;
        } catch (InvalidKeyException e) {
            throw new Exception("解密公钥非法,请检查");
        } catch (IllegalBlockSizeException e) {
            throw new Exception("密文长度非法");
        } catch (BadPaddingException e) {
            throw new Exception("密文数据已损坏");
        }
    }

    /**
     * 数组拼接
     * @param data1 数组1
     * @param data2 数组2
     * @return
     */
    public static byte[] addBytes(byte[] data1, byte[] data2) {
        byte[] data3 = new byte[data1.length + data2.length];
        System.arraycopy(data1, 0, data3, 0, data1.length);
        System.arraycopy(data2, 0, data3, data1.length, data2.length);
        return data3;
    }

    /**
     * 得到公钥
     *
     * @param key 密钥字符串(经过base64编码)
     * @throws Exception
     */
    public static PublicKey getPublicKey(String key) throws Exception {
        byte[] keyBytes;
        keyBytes = new BASE64Decoder().decodeBuffer(key);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(keySpec);
        return publicKey;
    }
}
其中用到的工具类Base64Util:

public class Base64Util {
    private static final char[] base64EncodeChars = new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' };
    private static byte[] base64DecodeChars = new byte[] { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 };
    private Base64Util() {}

    /**
     * 将字节数组编码为字符串
     *
     * @param data
     */
    public static String encode(byte[] data) {
        StringBuffer sb = new StringBuffer();
        int len = data.length;
        int i = 0;
        int b1, b2, b3;
        while (i < len) {
            b1 = data[i++] & 0xff;
            if (i == len) {
                sb.append(base64EncodeChars[b1 >>> 2]);
                sb.append(base64EncodeChars[(b1 & 0x3) << 4]);
                sb.append("==");
                break;
            }
            b2 = data[i++] & 0xff;
            if (i == len) {
                sb.append(base64EncodeChars[b1 >>> 2]);
                sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]);
                sb.append(base64EncodeChars[(b2 & 0x0f) << 2]);
                sb.append("=");
                break;
            }
            b3 = data[i++] & 0xff;
            sb.append(base64EncodeChars[b1 >>> 2]);
            sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]);
            sb.append(base64EncodeChars[((b2 & 0x0f) << 2) | ((b3 & 0xc0) >>> 6)]);
            sb.append(base64EncodeChars[b3 & 0x3f]);
        }
        return sb.toString();
    }


    /**
     * 将base64字符串解码为字节数组
     *
     * @param str
     */
    public static byte[] decode(String str) throws Exception{
        byte[] data = str.getBytes("GBK");
        int len = data.length;
        ByteArrayOutputStream buf = new ByteArrayOutputStream(len);
        int i = 0;
        int b1, b2, b3, b4;
        while (i < len) {


            /* b1 */
            do {
                b1 = base64DecodeChars[data[i++]];
            } while (i < len && b1 == -1);
            if (b1 == -1) {
                break;
            }


            /* b2 */
            do {
                b2 = base64DecodeChars[data[i++]];
            } while (i < len && b2 == -1);
            if (b2 == -1) {
                break;
            }
            buf.write((int) ((b1 << 2) | ((b2 & 0x30) >>> 4)));


            /* b3 */
            do {
                b3 = data[i++];
                if (b3 == 61) {
                    return buf.toByteArray();
                }
                b3 = base64DecodeChars[b3];
            } while (i < len && b3 == -1);
            if (b3 == -1) {
                break;
            }
            buf.write((int) (((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2)));


            /* b4 */
            do {
                b4 = data[i++];
                if (b4 == 61) {
                    return buf.toByteArray();
                }
                b4 = base64DecodeChars[b4];
            } while (i < len && b4 == -1);
            if (b4 == -1) {
                break;
            }
            buf.write((int) (((b3 & 0x03) << 6) | b4));
        }
        return buf.toByteArray();
    }
}
SHA256.java

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class SHA256 {
	
	/**
	 * 利用java原生的类实现SHA256加密
	 * 
	 * @param str 加密后的报文
	 * @return
	 */
	public static String getSHA256(String str) {
		MessageDigest messageDigest;
		String encodestr = "";
		try {
			messageDigest = MessageDigest.getInstance("SHA-256");
			messageDigest.update(str.getBytes("UTF-8"));
			encodestr = byte2Hex(messageDigest.digest());
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return encodestr;
	}
 
	/**
	 * 将byte转为16进制
	 * 
	 * @param bytes
	 * @return
	 */
	private static String byte2Hex(byte[] bytes) {
		StringBuffer stringBuffer = new StringBuffer();
		String temp = null;
		for (int i = 0; i < bytes.length; i++) {
			temp = Integer.toHexString(bytes[i] & 0xFF);
			if (temp.length() == 1) {
				stringBuffer.append("0");
			}
			stringBuffer.append(temp);
		}
		return stringBuffer.toString();
	}
}    

收不到异步通知排查方案#

问题原因#

异步通知地址没有报备过。
没有上送指定的异步通知地址。
异步地址必须外网可正常访问。

请求参数

Body 参数application/json

示例

返回响应

🟢200成功
application/json
Body

请求示例请求示例
Java
Shell
C#
PHP
响应示例响应示例
{}
修改于 2026-03-24 02:57:57
上一页
交易和退款结果通知
下一页
预授权撤销
Built with