商户接入指南 商户接入指南
  • V2
  • V3 (opens new window)
  • V2
  • V3 (opens new window)
  • 接入指南

    • 起步
    • 名词约定
    • 对接流程(必读)
    • 签名规约
    • 服务端接入流程
    • 3D集成指南V1(From提交)
    • 3D集成指南V2(风控插件)
  • 接入方案

    • 收银台模式

      • 内嵌JS-SDK
      • 跳转接入
    • 端到端模式

      • 快速开始
      • 商户收银台规范
    • 交易处理方案

      • 处理交易状态
        • 主动查询
          • 请求地址
          • 请求参数
          • 响应参数
        • 交易结果异步通知
        • 如何判断交易状态
          • 交易状态
          • paymentType+status
      • 交易数据处理方案
      • 交易状态处理方案
      • 自动续费场景处理方案
    • 开源建站工具插件支持

      • Magento235
      • Woocommerce
      • OpenCart
      • Prestashop
      • ZenCart
  • APIs

    • 交易下单

      • 收银台模式
      • 端到端模式
      • 退款和预授权
      • 修改交易信息
    • 交易查询

    • 快捷支付

    • 拒付查询

    • 物流信息

    • 交易账单

    • 币种汇率

    • 商户信息

  • 附录

  • v2

处理交易状态

# 处理交易状态


注意 :

1. 若交易同步返回状态为“ PROCESSING”,商户应等待 pingpong checkout 异步结果再进行业务处理。

2. 因此商户必须有机制保证在合适的时机查询到交易最终状态,或者接入异步通知


在唤起收银台,点击支付无错误的情况下,就产生了待处理的交易。PingPongPay提供两种获取交易状态的方式:

异步通知

主动查询

# 主动查询

调用接口 v2/query 可以主动查询单笔交易

# 请求地址

https://{host}/v2/query
1

# 请求参数

参数字段 参数类型 参数属性 参数说明
accId String(64) M PingPong 商户店铺编号
signType String(8) M 签名规约,支持 MD5、SHA256,具体⻅本文 “签名规约”一栏
sign String(256) M 签名内容,具体⻅本文“签名规约”一栏
transactionId String(64) C PingPong 交易流水号,与 merchantTransactionId 至少上送一项
merchantTransactionId String(64) C 商户网站交易流水号,与 transactionId 至少 上送一项

# 响应参数

参数字段 参数属性 参数说明
clientId M PingPong 商户商户号
accId M PingPong 商户店铺编号
transactionId M PingPong 交易流水号
merchantTransactionId M 商户网站的的交易流水号
code M 结果状态码
description M 结果描述
paymentType M 交易类型: DEBIT-直接付款 AUTH-预授权 REFUND-退款 CAPTURE-预授权确认 VOID-预授权取消 APPROVE-审核通过 REJECT-审核拒绝
currency M 交易币种
amount M 交易金额
transactionTime M 交易发起时间,yyyyMMddHHmmss
completeTime M 交易处理完成时间,yyyyMMddHHmmss
status M SUCCESS-成功 FAILED-失败 PROCESSING-进行中 REVIEW-待审核
signType M 签名规约,支持 MD5、SHA256,具体⻅本文“签名 方案”一栏
sign M 签名内容,具体⻅本文“签名规约”一栏
remark C 商户扩展字段
threeDSecure C 3DS 交易标示 Y/N

# 交易结果异步通知

  • 商户正常上报交易参数无误,发起正常的交易请求与流程,并且上送了notifyUrl,则会收到异步通知

  • pingpong checkout API v2 通过 POST 商户上送的notifyUrl 来发起通知,报文装填形式为String,并携带以下MIMEType:

Content-Type:x-www-form-urlencoded
1

# 报文示例

"notificationUrl=http://www.example.com/&amount=1.080000&clientId=2018092714313010016&code=000000&threeDSecure=N&sign=23EA484AFA4F39A5E1A53E7E379730AB&description=Transaction succeeded&transactionTime=1639638212000&transactionId=PS21121615033172714&checkoutType=NORMAL&paymentType=DEBIT&outFlowId=PS21121615033172714&merchantTransactionId=PShop20211216150322GA&accId=2018092714313010016291&signType=MD5&currency=USD&status=SUCCESS"
1

# 报文接收示例

    $inputStr = file_get_contents('php://input');
    parse_str($inputStr, $input);
    
    1
    2
    @RequestMapping(value = "/checkoutNotify", method = {RequestMethod.GET, RequestMethod.POST})
        public String checkoutCallback(HttpServletRequest httpServletRequest,HttpServletResponse response) {
            String bodyJson = NotifyUtils.getBodyJson(httpServletRequest);
            log.info("receive remote checkoutCallback notifyContent: {}", bodyJson);
            boolean result = callbackService.checkoutCallback(bodyJson);
            response.setStatus(result ? HttpServletResponse.SC_OK : HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            return result ? "OK" : "ERROR";
        }
        
        public class NotifyUtils {
    
        public static String getBodyString(HttpServletRequest httpServletRequest) {
            StringBuilder sb = new StringBuilder();
            ServletInputStream inputStream = null;
            BufferedReader reader = null;
            try {
                inputStream = httpServletRequest.getInputStream();
                reader = new BufferedReader(
                        new InputStreamReader(inputStream, StandardCharsets.UTF_8));
    
                char[] bodyCharBuffer = new char[1024];
                int len = 0;
                while ((len = reader.read(bodyCharBuffer)) != -1) {
                    sb.append(new String(bodyCharBuffer, 0, len));
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return sb.toString();
        }
    
        public static String getBodyJson(HttpServletRequest httpServletRequest) {
            String bodyString = NotifyUtils.getBodyString(httpServletRequest);
            String[] StringList = StringUtils.split(bodyString, "&");
            List<HashMap<String, String>> list = new ArrayList<>();
            HashMap<String, String> map = new HashMap<>(1);
            for (String stringItem :
                    StringList) {
                String[] chunks = StringUtils.split(stringItem, "=");
                map.put(chunks[0], chunks[1]);
    
            }
    
            return JSON.toJSONString(map);
        }
    }
    
    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
    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
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    // Make sure to add code blocks to your code group
    • 商户在成功收到异步处理结果后,需要在响应体中返回 HttpCode 为 200 并 且以字符串形式返回 OK, 表示商户已经成功收到异步结果通知,否则 pingpong checkout 会在随后的一 段时间内,以递增的时间间隔重发,最多重发 12 次,间隔为 2s/5s/5s/10s/30s/1m/10m/30m/1h/2h/1d/2d。

    • 具体送达时间受双方网络连接状态影响。。

    • 商户不能仅仅依赖于异步通知,如果⻓时间未收到交易结果,商户应该主动向 pingpong checkout 发起交易查询,查询对应的交易结果。


    注意 :

    1. notifyUrl需要填写商户自己系统的真实地址,不能随意填写

    2. notifyUrl必须是以https://的完整全路径地址,并且确保url中的域名和IP是外网可以访问的,不能填写localhost、127.0.0.1、192.168.x.x等本地或内网IP

    3. notifyUrl填写之前,商户需要尝试请求并自行检查网络连通性

    4. notify_url最后不携带参数,以免丢失参数,若一定要携带,请使用pathInfo的URL模式

    5. 异步通知可能不是最终结果,可能是PROCESSING,REVIEW等状态,需要注意处理

    6. 异步通知代码处理逻辑不能做登录态校验。

    7. 同样的通知可能会多次发送给商户系统,商户系统必须能够正确处理重复的通知。

    8. 商户侧对IP有防火墙策略限制的应将IP加入白名单


    生产 Notify Sever IP 沙箱 Notify Sever IP
    3.125.243.2 52.76.198.228
    3.126.196.22
    18.195.199.34

    # 如何判断交易状态

    # 交易状态

    交易状态是交易流程和结果的描述,不同业务模型有不同的规则,PingPong Pay API v2 采用paymentType来区分业务, status表示接口调用状态。paymentType+status是完整的交易状态描述。

    对于PingPongPay API v2 现有四种status可能被返回:

    SUCCESS-成功

    FAILED-失败

    PROCESSING-进行中

    REVIEW-待审核


    注意 :

    1. status只是对于当前请求操作的成功与否的描述,不能简单的等于交易状态

    2. 对于DEBIT业务,status与实际交易状态一致

    3. 对于接入了AUTH的用户,交易状态应根据paymentType+status进行组合判断


    # paymentType+status

    # DEBIT交易业务:

    状态 描述 状态类型
    SUCCESS
    已成功支付,交易成功 终态
    FAILED
    交易失败 本次支付终态,可以请求再次支付
    PROCESSING
    中间状态,等待进一步处理 中间状态
    REVIEW
    交易具有风险,需要人工审核 中间状态

    一旦交易到达终态,除非因为失败发起重新支付,都不应该再次接受异步通知的更改。交易在中间态的时候,需要等待下一个异步通知到达本次支付的终态。

    # AUTH交易业务:

    状态 描述
    SUCCESS
    不等于交易成功,需要根据具体的操作类型来判断
    FAILED
    交易失败
    PROCESSING
    中间状态,等待进一步处理
    REVIEW
    交易具有风险,需要人工审核

    # AUTH业务在checkout接口中的状态

    操作 状态 描述
    AUTH SUCCESS 预授权操作成功,不代表交易最终状态成功,后续还需发起CAPTURE
    AUTH FAILED 预授权操作失败

    详见预授权章节。

    上次更新: 2022/09/07, 11:39:45
    商户收银台规范
    交易数据处理方案

    ← 商户收银台规范 交易数据处理方案→

    杭州乒乓智能技术有限公司 | Copyright © 2015-2024 All rights reserved. pay.pingpongx.com
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式