快钱聚合支付(一码付)对接demo

备注:以下代码基于PHP laravel框架,引用了自带的函数。array_get($array, "key") 为数组中取元素,类似于$array["key"]。快钱后端语言为java,对接快钱时遇到了一些问题,今天整理下,希望可以帮到更多的人。

一、后端拼接唤起支付url

/**
  * 快钱一码付(聚合支付)相关配置
  */
$kuaiqian = [
        "merchantCode" => "10210xxxxxx",                                                    //商户会员号
        "merchantId"   => "812310xxxxx",                                                    //商户编号
        "terminalId"   => "71075xxxxx",                                                     //终端编号
        "key"          => "xxxxxxx",                                                        //支付秘钥
        "payUrl"       => "https://pay.99bill.com/prod/html/agent-static/index.html",       //快钱前端唤起支付url
        "returnUrl"    => "https://xxx/return_url",                                         //支付成功,前端回调url
]

/**
 * 拼接支付参数
 * @param $orderNumber
 */
function getPayUrl($orderNumber, $money)
{
    $data = [
        "requestTime"       => date("YmdHis"),
        "externalTraceNo"   => $orderNumber,
        "merchantCode"      => array_get($kuaiqian, "merchantCode"),
        "merchantId"        => array_get($kuaiqian, "merchantId"),
        "terminalId"        => array_get($kuaiqian, "terminalId"),
        "amt"               => $money,
        "returnUrl"         => array_get($kuaiqian, "returnUrl")."?orderNumber=".$orderNumber      //前端同步回调地址
    ];
    $sign = kuaiqian_sign($data);
    $data["secretInfo"] = $sign;
    $string = "";
    foreach ($data as $key => $value) {
        $string .= $key."=".$value."&";
    }
    return array_get($kuaiqian, "payUrl")."?".rtrim($string, "&");
}

/**
 * 快钱支付签名
 */
function kuaiqian_sign($data)
{
    ksort($data);
    $res = "";
    foreach ($data as $key => $value) {
        if (!$value) continue;                      //参数值为空时不参与签名
        $res .= $key."=".$value."&";
    }
    $stringSignTemp = $res."key=".array_get($kuaiqian, "key");
    return strtoupper(md5($stringSignTemp));
}

二、回调签名(和支付、微信不同的是快钱的回调地址需要提前和业务联系配置)

/**
 * 支付异步回调
 * @param Request $request
 */
function payNotify(PayRepository $payRepository)
{
    $request = file_get_contents("php://input");
    $request = explode("&", $request);
    //将回调数组转为完整数组
    foreach ($request as $data) {
        $tmp = explode("=", $data);
        $result[array_get($tmp, "0")] = urldecode(array_get($tmp, "1"));
    }
    //支付回调签名验证
    $signVerify = kuaiqian_notify_sign_verify($result);
    //签名不通过
    if (!$signVerify) {
        return "1";
    }
    //系统内部订单号
    $orderNumber = array_get($result, "externalTraceNo");
    //订单已经支付成功,不需要重复回调
    if (array_get($payOrder, "status") != PayOrder::PAY_ORDER_STATUS_NOT) {
        return "0";
    }
    if (array_get($result, "processFlag") === "0") {   //支付成功,处理内部业务逻辑
        $result = "success";   //处理支付成功以后的业务逻辑
        if (!$result) {
            return "1";
        } else {
            return "0";
        }
    } else {                                           //支付不成功,也不允许再次回调
        return "0";
    }
}

/**
 * 快钱支付接口通知验签结果校验
 * @param  $datas  array  快钱回调完整报文
 */
function kuaiqian_notify_sign_verify($datas)
{
    $signature = array_get($datas, "signature");    //获取签名
    //获取参与验签的数组节点(array_only()为laravel封装的函数,获取数组中指定键的参数,可以自己封装。)
    $datas = array_only($datas, ["processFlag", "txnType", "orgTxnType", "amt", "externalTraceNo", "orgExternalTraceNo",
        "terminalOperId", "authCode", "RRN", "txnTime", "shortPAN", "responseCode", "cardType", "issuerId"]);
    //节点值为空时屏蔽节点,不需要参与验签
    foreach ($datas as $key => $value) {
        if ($datas[$key] === "") {
            unset($datas[$key]);
        }
    }
    $result = implode("", $datas);        //等待验签字符串拼接
    $publicKey = openssl_get_publickey(file_get_contents(public_path("xxxx/public.pem")));    #特别强调:验签公钥快钱给的是.cer格式,PHP需要转为pem(openssl x509 -inform der -in xx.cer  xx.pem)
    return openssl_verify($result, base64_decode($signature), $publicKey);
}

三、后记
快钱后端为Java,导致回调验签的时候费了好大力气才搞定,今天整理了下,需要的伙伴可以试试,有问题可以私我。(快钱做大做强了,但技术对接服务这块真的不怎么样,坑死。)

你可能感兴趣的:(快钱聚合支付(一码付)对接demo)