php版工行聚合支付和e支付

以下是自己写的调用支付和退款和查询订单

class ICBCRefundBizContentParameter {

    // 商户、部门编号
    public $mer_id;

    // 退货流水号,商户系统生成的退款编号,每次部分退款需生成不同的退款编号
    public $outtrx_serial_no;

    // 商户订单号 ,商户订单号或工行订单号必输其一
    public $out_trade_no;

    // 退款金额,单位:分
    public $ret_total_amt;

    // 交易币种,目前只支持人民币,送001
    public $trnsc_ccy;

    // 商户在工行API平台的APPID
    public $icbc_appid;

    // 商户清算账号,暂不使用
    public $mer_acct;

    /**
     * ICBCRefundBizContentParameter constructor.
     * @param string $refundId
     * @param string $orderId
     * @param string $money
     */
    public function __construct($subMerchantId, $refundId, $orderId, $money){
        $this->mer_id = $subMerchantId;
        $this->outtrx_serial_no = $refundId;
        $this->out_trade_no = $orderId;
        $this->ret_total_amt = $money;
        $this->trnsc_ccy = "001";
        $this->icbc_appid = "";
//        $this->mer_acct = "";
    }
}
<?php

class ICBCPayBizContentParameter {

    // 支付方式,9-微信;10-支付宝
    public $pay_mode;

    // 收单接入方式,5-APP,7-微信公众号,8-支付宝生活号,9-微信小程序
    public $access_type;

    // 交易日期时间,格式为yyyy-MM-dd’T’HH:mm:ss
    public $orig_date_time;

    // 设备号
    public $decive_info;

    // 商品描述,商品描述交易字段格式根据不同的应用场景按照以下格式:1)PC网站:传入浏览器打开的网站主页title名-实际商品名称 ;2)公众号:传入公众号名称-实际商品名称;3)H5:传入浏览器打开的移动网页的主页title名-实际商品名称;4)线下门店:门店品牌名-城市分店名-实际商品名称;5)APP:传入应用市场上的APP名字-实际商品名称
    public $body;

    // 订单号
    public $out_trade_no;

    // 订单金额
    public $total_fee;

    // 支付币种 人名币
    public $fee_type = "001";

    // 用户端IP
    public $spbill_create_ip;

    // 商户代码
    public $mer_id;

    // 收单协议编号
    public $mer_prtcl_no;

    // 商户账号,目前暂不支持
    public $mer_acct;

    // 交易过期时间 支付宝和微信使用
    public $expire_time;

    // 附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
    public $attach;

    // 商户在微信开放平台注册的APPID,支付方式为微信时不能为空
    public $shop_appid;

    // 商户在工行API平台的APPID
    public $icbc_appid;

    // 回调通知地址
    public $mer_url;

    // 通知类型 HS为发送 AG为不发送
    public $notify_type = "HS";

    /**
     * ICBCPayBizContentParameter constructor.
     * @param $subMerchantId 商户号
     * @param string $orderId 订单id
     * @param string $payType 支付类型 9-微信;10-支付宝
     * @param string $mobileDecive 手机设备号
     * @param string $money 订单金额 (分)
     * @param string $attach 附加数据
     * @param string $clientIp 客户端ip
     * @param string $notifyUrl 回调地址
     */
    public function __construct($subMerchantId, $mer_prtcl_no, $orderId, $payType, $mobileDecive,$money,$attach,$clientIp,$notifyUrl){
        $this->spbill_create_ip = $clientIp;
        $this->pay_mode = $payType;
        $this->decive_info = $mobileDecive;
        $this->attach = $attach;
        $this->out_trade_no = $orderId;
        $this->total_fee = $money;
        $this->icbc_appid = "";
        $this->mer_url = $notifyUrl;
//        $this->mer_acct = $subMerchantId;
        $this->mer_id = $subMerchantId;
        $this->mer_prtcl_no = $mer_prtcl_no;
        $this->orig_date_time = substr(date("c",time()),0,strpos(date("c",time()),"+"));
        $this->expire_time = "180";//秒
        $this->body = "";
        $this->access_type = "5";

        if ($payType == 9) {
            $this->shop_appid = C("icbc_weChat_shopAppID");

        }

    }
}
<?php

class ICBCEPayBizContentParameter {

    // 工行API平台的APPID
    public $icbc_appid;

    // 交易日期时间,格式为:YYYYMMDDHHmmss,要求在银行系统当前时间的前1小时和后12小时范围内,否则判定交易时间非法\
    public $order_date;

    // 商户订单号
    public $order_id;

    // 订单金额,单位分
    public $amount;

    // 分期付款期数,1、3、6、9、12、18、24;1代表全额付款,必须为以上述值,否则订单校验不通过
    public $installment_times;

    // 交易币种,目前工行只支持使用人民币(001)支付
    public $cur_type;

    // 商户编号
    public $mer_id;

    // 收单协议编号
    public $mer_prtcl_no;

    // 商户账号,商户入账账号,只能交易时指定。(商户付给银行手续费的账户,可以在开户的时候指定,也可以用交易指定方式;用交易指定方式则使用此商户账号)
    public $mer_acct;

    // 通知商户URL,必须合法的URL,交易结束,银行使用HTTP协议POST方式向此地址发送通知信息;目前只支持80端口
    public $merURL;

    // 支付成功回显页面,支付成功后,跳转至该页面显示
    public $return_url;

    // 返回商户变量, 工行给商户发送商户通知时会原样返回,可参考响应报文中attach字段(可理解为附加参数)
    public $mer_var;

    // 只走H5标志,0-不限制,1-只走H5,默认0。商户如需嵌入APP内使用,h5_flag只能送1
    public $h5_flag;

    /**
     * ICBCEPayBizContentParameter constructor.
     * @param $subMerchantId 商户号
     * @param string $orderId 订单号
     * @param string $money 金额
     * @param string $attach 附加字段
     * @param boolean $isInApp 是否在app内嵌入 true 是  false 否
     * @param string $notifyUrl 回调地址
     * @param string $returnUrl 支付完跳转地址
     */
    public function __construct($subMerchantId, $mer_prtcl_no, $orderId, $money, $attach, $isInApp, $notifyUrl, $returnUrl){
        $this->icbc_appid = "";
        $this->order_date = date("YmdHis");
        $this->order_id = $orderId;
        $this->amount = $money;
        $this->installment_times = "1";
        $this->cur_type = "001";
        $this->mer_id = $subMerchantId;
        $this->mer_prtcl_no = $mer_prtcl_no;
//        $this->mer_acct = C("icbc_merAcct");
//        $this->mer_acct = "";
        $this->merURL = $notifyUrl;
        $this->return_url = $returnUrl;
        $this->mer_var = $attach;
        if ($isInApp) {
            $this->h5_flag = "1";
        }
    }
}
<?php

namespace Org\IcbcPhp;

use Exception;

/**
 * Class ICBCPay
 * 工银支付
 */
class ICBCPay
{

    private $client;

    private $payType;

    /**
     * ICBCPay constructor.
     * @param string $payType 9 微信 10 支付宝 11 e支付
     */
    public function __construct($payType)
    {
        $this->payType = $payType . "";
        if ($payType == "9" || $payType == "10" || !$payType) {
            $this->client = new DefaultIcbcClient(C("icbc_app_id"), C("icbc_private_key"), C("icbc_sign_type"), C("icbc_charset"), C("icbc_format"), C("icbc_gateway_public_key"), C("icbc_encryptKey"), C("icbc_encryptType"), "", "");
        } elseif ($payType == "11") {
            $this->client = new UiIcbcClient(C("icbc_app_id"), C("icbc_private_key"), C("icbc_sign_type"), C("icbc_charset"), C("icbc_format"), C("icbc_gateway_public_key"), C("icbc_encryptKey"), C("icbc_encryptType"), "", "");
        }
    }

    /**
     * app 支付宝和微信下单
     * 张志强
     * 2021-01-12
     * @param string $subMerchantId 商户号
     * @param string $mer_prtcl_no 协议编号
     * @param string $orderId 订单号
     * @param string $money 金额
     * @param string $decive 设备号
     * @param string $attach 附加字段
     * @param string $clientIp 设备ip
     * @param string $notifyUrl 回调地址
     * @return false|string
     * @throws Exception
     */
    public function appPay($subMerchantId, $mer_prtcl_no, $orderId, $money, $decive, $attach, $clientIp, $notifyUrl)
    {
        if ($this->payType == 11) {
            throw new Exception("请使用e支付的接口");
        }
        $data = [
            'serviceUrl' => 'https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/consumepurchase/V1',
            'biz_content' => get_object_vars(new ICBCPayBizContentParameter($subMerchantId, $mer_prtcl_no, $orderId . "", $this->payType, $decive, $money . "", $attach, $clientIp, $notifyUrl)),
            'extraParams' => [],
            'method' => "POST",
            'isNeedEncrypt' => true
        ];

        return $this->client->execute($data, $orderId, "");
    }

    /**
     * e支付 h5
     * 张志强
     * 2021-01-12
     * @param string $subMerchantId 商户号
     * @param string $mer_prtcl_no 协议编号
     * @param string $orderId string     订单号
     * @param string $money string      金额
     * @param string $attach string     附加字段
     * @param boolean $isInApp bool 是否嵌入app内
     * @param string $notifyUrl 回调地址
     * @param string $returnUrl 支付完跳转地址
     * @return string
     * @throws Exception
     */
    public function ePay($subMerchantId, $mer_prtcl_no, $orderId, $money, $attach, $isInApp, $notifyUrl, $returnUrl)
    {
        if ($this->payType != 11) {
            throw new Exception("请使用聚合支付的接口");
        }
        $data = [
            'serviceUrl' => 'https://gw.open.icbc.com.cn/ui/cardbusiness/epayh5/ui/consumption/V1',
            'biz_content' => get_object_vars(new ICBCEPayBizContentParameter($subMerchantId, $mer_prtcl_no, $orderId . "", $money . "", $attach, $isInApp, $notifyUrl, $returnUrl)),
            'extraParams' => [],
            'method' => "POST",
            'isNeedEncrypt' => true
        ];

        return $this->client->buildPostForm($data, $orderId, "");
    }

    /**
     * 退款
     * 张志强
     * 2021-01-12
     * @param string $subMerchantId 商户编号
     * @param string $refundId 自己生成的唯一退款id
     * @param string $orderId 订单号
     * @param string $money 金额
     * @return false|string
     * @throws Exception
     */
    public function refund($subMerchantId, $refundId, $orderId, $money)
    {
        // 退款
        $data = [
            'serviceUrl' => 'https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/merrefund/V1',
            'biz_content' => get_object_vars(new ICBCRefundBizContentParameter($subMerchantId, $refundId . "", $orderId . "", $money . "")),
            'extraParams' => [],
            'method' => "POST",
            'isNeedEncrypt' => true
        ];
        return $this->client->execute($data, $orderId, "");
    }

    // 查询订单

    /**
     * @param $subMerchantId
     * @param $serial_number
     * @return false|string
     * @throws Exception
     */
    public function selectIcbcOrder($subMerchantId, $serial_number)
    {
        $data = [
            'serviceUrl' => 'https://gw.open.icbc.com.cn/api/cardbusiness/aggregatepay/b2c/online/orderqry/V1',
            'biz_content' => [
                'mer_id' => $subMerchantId,
                'out_trade_no' => $serial_number,
                'deal_flag' => "0",
                'icbc_appid' => C('icbc_app_id')
            ],
            'extraParams' => [],
            'method' => "POST",
            'isNeedEncrypt' => true
        ];

        return $this->client->execute($data, microtime(), "");
    }
}

支付回调

/**
     * 工银支付回调
     * @throws Exception
     */
    public function icbcNotify() {
        $file_pointer = fopen(APP_PATH."/Lib/Action".__GROUP__."/aa.txt","a+");
        fwrite($file_pointer,"回调开始");
        try {
            // 获取参数
            $responseStr = urldecode(file_get_contents("php://input"));
            if (!$responseStr) {
                throw new Exception("【".date("Y-m-d H:i:s")."】  参数不能为空\r\n");
            }
            $response = explode("&",$responseStr);
            $responseArr = [];
            $sign = "";
            foreach ($response as $k => $v) {
                if (strstr($v,"=",true) == 'sign') {
                    $sign = substr(strstr($v,"=",false),1);
                } else {
                    $responseArr[strstr($v,"=",true)] = substr(strstr($v,"=",false),1);
                }
            }

            // 生成待签名字符串
            $path = parse_url('域名' +'接口名', PHP_URL_PATH);
            $respBizContentStr = WebUtils::buildOrderedSignStr($path,$responseArr);

            // 验证签名1
            $passed = IcbcSignature::verify($respBizContentStr, $responseArr['sign_type'], C("icbc_gateway_public_key"), $responseArr['charset'], $sign,'');
            if (!$passed) {
                $responseArr = json_encode($responseArr);
                throw new Exception("【".date("Y-m-d H:i:s")."】  icbc sign verify not passed!\r\n订单信息为【{$responseArr}】签名为【{$sign}】\r\n");
            }

            // 返回业务参数
            $bizContent = json_decode($responseArr['biz_content'],true);

            $merOrderId = $bizContent['out_trade_no'];
            $notify_return_code = $bizContent['return_code'];

            // 验证返回消息码是否正确
            if ($notify_return_code !== "0") {
                return $this->response("-1","error");
            }

            // 修改unipay_log
            $result = M('unionpay_log')->data(['is_valid' => 2])->where(['serial_number'=>$merOrderId])->save();
            if ($result === false) {
                throw new Exception("【".date("Y-m-d H:i:s")."】  修改unipay_log失败!\r\n订单信息为【{$responseArr}】签名为【{$sign}】\r\n");
            }

        	// 自己的业务逻辑
			//return $this->response("0","success");成功响应
			//return $this->response("-1","error");失败响应

        } catch (Exception $exception) {
            fwrite($file_pointer,$exception->getMessage());
            return $this->response("-1","error");
        }
    }

    /**
     * 工行回调应答
     * 张志强
     * 2021-07-15
     */
    private function response($return_code,$return_msg) {
        // 应答
        $respBizContent = array(
            'return_code' => $return_code,
            'return_msg' => $return_msg,
            'msg_id' => microtime()
        );

        $answer['response_biz_content'] = json_encode($respBizContent);
        $answer['sign_type'] = C('icbc_sign_type');
        $answer['sign'] = IcbcSignature::sign(substr(json_encode($answer),1),C("icbc_sign_type"),C("icbc_private_key"),C("icbc_charset"),'');

        return json_encode($answer);
    }

强调:
在支付回调签名验证的时候的path不要自己手写,会发生验签不通过,切记要用

 $path = parse_url('域名' +'接口名', PHP_URL_PATH);

php工行SDK下载地址

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值