php版工行聚富通支付

<?php
include_once "icbc-api-sdk-cop-php/DefaultIcbcClient.php";
include_once "icbc-api-sdk-cop-php/UiIcbcClient.php";
include_once "icbc-api-sdk-cop-php/WebUtils.php";
include_once "icbc-api-sdk-cop-php/IcbcSignature.php";
include_once "icbc-api-sdk-cop-php/IcbcConstants.php";
include_once "icbc-api-sdk-cop-php/IcbcJftPayI.php";

class IcbcPay
{

    public static $app_id = "";
    public static $private_key = '私钥';
    public static $public_key = '公钥';
    public static $getaway_public_key = '工行公钥';
    public static $encrypt_key = '加密串';
    public static $wechatAppletAppId = "微信小程序appid";
    public static $payNotifyUrl = '/apk49/Pay/icbcPayNotify';
    public static $refundNotifyUrl = '/apk49/PayRefund/icbcRefundNotify';

    /**
     * 构建数据
     * @param string $service_url
     * @param string $request_type
     * @param array $biz_content
     * @param bool $isNeedEncrypt
     * @return array
     * @author 张志强
     */
    private static function buildData(string $service_url, string $request_type, array $biz_content, bool $isNeedEncrypt = false): array
    {
        return [
            'serviceUrl' => $service_url,
            'biz_content' => $biz_content,
            'extraParams' => [],
            'method' => $request_type,
            'isNeedEncrypt' => $isNeedEncrypt
        ];
    }

    /**
     * 验签
     * @param string $respStr
     * @return false|string
     * @throws Exception
     */
    public static function verifySign(string $respStr)
    {
        $response = explode("&", $respStr);
        $responseArr = [];
        $sign = "";
        foreach ($response as $v) {
            if (strstr($v, "=", true) == 'sign') {
                $sign = substr(strstr($v, "="), 1);
            } else {
                $responseArr[strstr($v, "=", true)] = substr(strstr($v, "="), 1);
            }
        }

        $path = parse_url($_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'] . $_SERVER["REQUEST_URI"], PHP_URL_PATH);
        $respBizContentStr = WebUtils::buildOrderedSignStr($path, $responseArr);

        //解析响应
        $passed = IcbcSignature::verify($respBizContentStr, IcbcConstants::$SIGN_TYPE_RSA, self::$getaway_public_key, IcbcConstants::$CHARSET_UTF8, $sign, "");
        if (!$passed) {
            throw new Exception("icbc sign verify not passed!");
        }

        //返回解析结果
        return base64_decode(json_decode(str_replace("%2B", '+', $responseArr['biz_content']), true)['notifyData']);
    }

    /**
     * 加签
     * @param string $copReturnCode
     * @param string $copReturnMsg
     * @return string
     * @throws Exception
     */
    public static function sign(string $copReturnCode, string $copReturnMsg): string
    {
        $responseBizContentArr = [
            'return_code' => $copReturnCode,
            'return_msg' => $copReturnMsg,
            'msg_id' => date("YmdHis", time())
        ];

        $signStr = '"response_biz_content":'.json_encode($responseBizContentArr).',"sign_type":"'.IcbcConstants::$SIGN_TYPE_RSA2.'"';

        $signArr = [
            'response_biz_content' => $responseBizContentArr,
            'sign_type' => IcbcConstants::$SIGN_TYPE_RSA2,
        ];

        $signArr['sign'] = IcbcSignature::sign($signStr, IcbcConstants::$SIGN_TYPE_RSA2, self::$private_key, IcbcConstants::$CHARSET_UTF8, '');

        return json_encode($signArr);
    }

    /**
     * 发起ui界面的支付 e支付
     * @param string $service_url
     * @param string $request_type
     * @param array $biz_content
     * @return string
     * @author 张志强
     */
    public static function ui(string $service_url, string $request_type, array $biz_content): string
    {
        $data = self::buildData($service_url, $request_type, $biz_content);

        $uiClient = new UiIcbcClient(self::$app_id, self::$private_key, IcbcConstants::$SIGN_TYPE_RSA2, IcbcConstants::$CHARSET_UTF8, IcbcConstants::$FORMAT_JSON, self::$getaway_public_key, self::$encrypt_key, IcbcConstants::$ENCRYPT_TYPE_AES, "", "");

        return $uiClient->buildPostForm($data, time() . '', '');
    }

    /**
     * 发起无界面的支付
     * @param string $service_url
     * @param string $request_type
     * @param array $biz_content
     * @return array
     * @throws Exception
     * @author 张志强
     */
    public static function api(string $service_url, string $request_type, array $biz_content): array
    {
        $data = self::buildData($service_url, $request_type, $biz_content, true);

        $apiClient = new DefaultIcbcClient(self::$app_id, self::$private_key, IcbcConstants::$SIGN_TYPE_RSA2, IcbcConstants::$CHARSET_UTF8, IcbcConstants::$FORMAT_JSON, self::$getaway_public_key, self::$encrypt_key, IcbcConstants::$ENCRYPT_TYPE_AES, "", "");

        $result = $apiClient->execute($data, time() . '', '');

        return json_decode($result, true);
    }

    /**
     * 单笔支付
     * @param $orderId string 订单号
     * @param $icbc_jft_submerchant_num string 子商户号
     * @param $money string 支付金额(元)
     * @param $rate string 费率
     * @return array
     * @throws Exception
     */
    public static function singleOrderPay(string $orderId, string $icbc_jft_submerchant_num, string $money, string $rate): array
    {
        $service_url = 'https://gw.open.icbc.com.cn/api/jft/api/pay/gen/pre/order/V1';
        $server = explode(":", $_SERVER['HTTP_HOST']);
        $biz_content = [
            'appId' => self::$app_id,
            'outVendorId' => $icbc_jft_submerchant_num,     // 收方商户编号
            'outUserId' => $icbc_jft_submerchant_num,       // 用户外部编号
            'notifyUrl' => 'http://'.$server[0].self::$payNotifyUrl,             // 回调地址
            'outOrderId' => $orderId,                       // 合作方订单id(唯一)
            'goodsName' => '物业账单',                       // 商品名称
            'trxChannel' => '01',                           // 交易渠道 固定送01:手机APP,否则校验不过
            'payAmount' => $money,                          // 支付金额(元)整数位不超8位,小数位不超2位
            'subMerRateWx' => $rate,                        // 微信支付费率
            'subMerRateZfb' => $rate,                       // 支付宝支付费率
            'subMerRateOwn' => $rate,                       // e支付本行卡费率
            'subMerRateOther' => $rate,                     // e支付他行卡费率
            'subMerRateVipCard' => $rate,                   // 会员卡费率
            'subMerRateUnionPay' => $rate,                  // 云闪付费率
            'version' => '1.0.1'
        ];

        $result = self::api($service_url, 'POST', $biz_content);
        if ($result['return_code'] != '10100000') {
            throw new Exception($result['return_msg']);
        }

        return $result;
    }


    /**
     * 并笔支付
     * @param string $parentOrderId 父订单id
     * @param string $goodsName 商品名称
     * @param string $money 金额
     * @param array $subOrder 子订单信息
     * @return array
     * @throws Exception
     */
    public static function multipleOrderPay(string $parentOrderId, string $goodsName, string $money, array $subOrder): array
    {
        $service_url = 'https://gw.open.icbc.com.cn/api/jft/api/pay/mergepay/gen/order/V1';

        $biz_content = [
            'appId' => self::$app_id,
            'outUserId' => '1',                         // 用户外部编号(并笔支付可以随便输入不影响子商户)
            'notifyUrl' => self::$payNotifyUrl,         // 回调地址
//            'jumpUrl' => '',                          // 商户跳转URL
            'outOrderId' => $parentOrderId,             // 合作方订单id(唯一)
            'goodsName' => $goodsName,                  // 商品名称
            'trxChannel' => '01',                       // 交易渠道 固定送01:手机APP,否则校验不过
            'payAmount' => $money,                      // 支付金额(元)整数位不超8位,小数位不超2位
            'version' => '1.0.1',                       // 工行版本号
            'suborders' => $subOrder                    // 子订单
        ];

        return self::api($service_url, 'POST', $biz_content);
    }

    /**
     * h5单笔埋名支付 跳转微信小程序
     * @param string $orderId 订单id
     * @param string $icbc_jft_submerchant_num
     * @param string $money
     * @param string $goodsName
     * @param string $ip
     * @param string $rate
     * @param string $openid
     * @return array
     * @throws Exception
     * @author 张志强
     * @creatime 2022-08-24
     */
    public static function h5SinglePay(string $orderId, string $icbc_jft_submerchant_num, string $money, string $goodsName, string $ip, string $rate, string $openid): array
    {
        $service_url = 'https://gw.open.icbc.com.cn/api/jft/api/pay/add/h5/traceless/order/V2';
        $server = explode(":", $_SERVER['HTTP_HOST']);
        $biz_content = [
            'appId' => self::$app_id,
            'outOrderId' => $orderId,                           // 合作方订单id(唯一)
            'outVendorId' => $icbc_jft_submerchant_num,         // 收方商户编号
            'outUserId' => $icbc_jft_submerchant_num,           // 用户外部编号(并笔支付可以随便输入不影响子商户)
            'payAmount' => $money,                              // 支付金额(元)整数位不超8位,小数位不超2位
            'payType' => '01',                                  // 合并支付表示 01 代表单笔支付
            'payMode' => '01',                                  // 支付模式 01 微信小程序 02 支付宝生活号 03 微信公众号
            'notifyUrl' => 'http://'.$server[0].self::$payNotifyUrl,                 // 回调地址
            'goodsName' => $goodsName,                          // 商品名称
            'trxIp' => $ip,                                     // 交易ip,支付提交的用户的ip地址
            'trxChannel' => '03',                               // 交易渠道 01:手机APP
            'subMerRateWx' => $rate,                            // 微信支付费率
            'subMerRateZfb' => $rate,                           // 支付宝支付费率
            'tpAppId' => self::$wechatAppletAppId,
            'tpOpenId' => $openid,
            'autoConfirm' => '1',                       // 是否及时解冻 1 是 0 否 商户为担保模式有效 默认是0
        ];

        $result = self::api($service_url, 'POST', $biz_content);
        if ($result['return_code'] != '10100000') {
            throw new Exception($result['return_msg']);
        }

        return $result;
    }

    /**
     * h5并笔埋名支付 跳转微信小程序
     * @throws Exception
     * @author 张志强
     * @creatime 2022-08-24
     */
    public static function h5MultiplePay(string $orderId, string $icbc_jft_submerchant_num, string $money, string $goodsName, string $ip, array $subOrder, string $openid): array
    {
        $service_url = 'https://gw.open.icbc.com.cn/api/jft/api/pay/add/h5/traceless/order/V2';

        $biz_content = [
            'appId' => self::$app_id,
            'outOrderId' => $orderId,             // 合作方订单id(唯一)
            'outUserId' => $icbc_jft_submerchant_num,                         // 用户外部编号(并笔支付可以随便输入不影响子商户)
            'payAmount' => $money,                      // 支付金额(元)整数位不超8位,小数位不超2位
            'payType' => '02',                          // 合并支付表示 01 代表单笔支付 02 并笔支付
            'payMode' => '01',                          // 支付模式 01 微信小程序 02 支付宝生活号 03 微信公众号
            'notifyUrl' => self::$payNotifyUrl,         // 回调地址
            'goodsName' => $goodsName,                  // 商品名称
            'trxIp' => $ip,                             // 交易ip,支付提交的用户的ip地址
            'trxChannel' => '03',                       // 交易渠道 01:手机APP
            'tpAppId' => IcbcJftPay::$wechatAppletAppId,// 小程序appid
            'tpOpenId' => $openid,                      // 小程序对应的openid
            'autoConfirm' => '1',                       // 是否及时解冻 1 是 0 否 商户为担保模式有效 默认是0
            'subOrders' => $subOrder                    // 子订单信息
        ];

        return self::api($service_url, 'POST', $biz_content);
    }

    /**
     * 订单查询
     * @param $orderId string 订单号
     * @return array
     * @throws Exception
     */
    public static function getOrder(string $orderId): array
    {
        $service_url = 'https://gw.open.icbc.com.cn/api/jft/api/pay/query/order/V1';

        $biz_content = [
            'appId' => self::$app_id,
            'outOrderId' => $orderId,                      // 订单号
        ];

        return self::api($service_url, 'POST', $biz_content);
    }

    /**
     * 单笔退款
     * @param string $subMerchantId
     * @param string $orderId
     * @param string $refundNum
     * @param string $refundAmount
     * @return void
     * @throws Exception
     */
    public static function refund(string $subMerchantId, string $orderId, string $refundNum, string $refundAmount, string $paltformAmount): void
    {
        $service_url = 'https://gw.open.icbc.com.cn/api/jft/api/pay/refund/accept/V1';
        $server = explode(":", $_SERVER['HTTP_HOST']);
        $biz_content = [
            'appId' => self::$app_id,
            'vendorId' => $subMerchantId,
            'userId' => $subMerchantId,
            'payType' => '01',
            'orderId' => $orderId,
            'refundId' => $refundNum,
            'refundAmount' => $refundAmount,
            'notifyUrl' => 'http://'.$server[0].self::$refundNotifyUrl,
            'fixedCommissionOwn' => $paltformAmount,
            'fixedCommissionOther' => $paltformAmount,
            'fixedCommissionWx' => $paltformAmount,
            'fixedCommissionZfb' => $paltformAmount,
            'fixedCommissionDigital' => $paltformAmount,
            'fixedCommission' => $paltformAmount
        ];
//        dump($biz_content);
        $result = self::api($service_url, 'POST', $biz_content);
//        dump($result);die();
        if ($result['return_code'] != '0') {
            throw new Exception($result['return_msg']);
        }
    }

    /**
     * 单笔退款查询
     * @param string $subMerchantId
     * @param string $orderId
     * @param string $refundNum
     * @return array
     * @throws Exception
     */
    public static function queryRefund(string $subMerchantId, string $orderId, string $refundNum): array
    {
        $service_url = 'https://gw.open.icbc.com.cn/api/jft/api/pay/refund/query/V1';

        $biz_content = [
            'appId' => self::$app_id,
            'vendorId' => $subMerchantId,
            'payType' => '01',
            'orderId' => $orderId,
            'refundId' => $refundNum
        ];

        $result = self::api($service_url, 'POST', $biz_content);
        if ($result['return_code'] !== '0') {
            throw new Exception($result['return_msg']);
        }
        return $result;
    }
}

调用示例

<?php 
	$wechatApplet = A("WechatApplet");
    $openid = $wechatApplet->get_wx_openid($wechatApplet->_wx_appid, $wechatApplet->_wx_secret, $code);
    $prePay = IcbcPay::h5SinglePay($orderReturn['serialNumber'], $mchid, bcdiv($orderReturn['totalAmount'], 100, 2), $orderReturn['orderDesc'], $ip, $orderReturn['rate'], $openid['openid']);
    $return['payData'] = json_decode($prePay['paySign'], true);

回调示例

public function icbcPayNotify(): void
    {
        vendor("IcbcPay/IcbcPay");
        try {
            // 接收数据
            // 获取参数
            $responseStr = urldecode(file_get_contents("php://input"));
            if (!$responseStr) {
                throw new Exception("接收不到参数");
            }

            addTxtLog("icbcPayNotifl", "工行聚富通支付回调原始数据头--->" . $responseStr);

            // 验证签名
            $resourceData = json_decode(IcbcPay::verifySign($responseStr), true);
            // 验证状态
            if ($resourceData['respCode'] != '00000' || $resourceData['orderStatus'] != '02') {
                throw new Exception("支付状态不正确");
            }

            addTxtLog("icbcPayNotifl", "工行聚富通支付回调验签解析数据--->" . json_encode($resourceData));

            // 防止回调运行时间长微信多次调用回调
            $lock = F("appletCallbackLock_" . $resourceData['orderId']);
            if (!$lock) {
                F("appletCallbackLock_" . $resourceData['orderId'], 1);

                // 判断订单类型
                switch (substr($resourceData['orderId'], -2)) {
                    case 'yx':  
                        $orderType = 3;
                        break;
                    case 'wo':  
                        $orderType = 4;
                        break;
                    case 'xw':  
                        $orderType = 5;
                        break;
                    default;
                        $orderType = 0;
                }

                if ($orderType == 0) {
                    throw new Exception("订单类型不对");
                }

                if ($resourceData['payMethod'] == '01') {
                    $payType = 'epay';
                } else {
                    $payType = 'icbcPay';
                }

                // 发送消息
                $this->sendMessage($resourceData['orderId'], $payType, 2, 1, $orderType, $this->judgeIsFormalData());

                F("appletCallbackLock_" . $resourceData['orderId'], NULL);

                addTxtLog("icbcPayNotifl", "工行聚富通支付回调数据成功");

                echo IcbcPay::sign(0, 'success');
            }
        } catch (Exception $exception) {
            $error = $exception->getMessage();
            addTxtLog("icbcPayNotifl", "工行聚富通支付回调数据错误--->$error");
            echo IcbcPay::sign(1, 'error');
        }
    }

php工行sdk下载地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值