以下是自己写的调用支付和退款和查询订单
<?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);