php 接入建行惠市宝的验签规则
官方提供的代码包,只有java代码示例,费了九牛二虎之力,在群里沟通了应该有一个星期,把建行的验签规则的php写法完成了。大家各取所需。
<?php
namespace app\data\repository\api;
use app\data\repository\common\CommonRepo;
use think\admin\extend\CodeExtend;
use think\admin\extend\HttpExtend;
/**
* 惠市宝接口封装(建行)
* Class Huishibao
* @package app\data\repository\api
*/
class Huishibao
{
/**
* 生成订单接口
*
* @param string $order_no
* @param float $amount
* @param string $openid
* @return array
*/
public function reqGatherPlaceorder($order_no, $amount, $openid)
{
$url = 'https://xxx/gatherPlaceorder';
$amount = CommonRepo::returnMoney($amount);
$param = [
'Ittparty_Stm_Id' => config('huishibao.Ittparty_Stm_Id'), // 发起渠道编号,默认送5个0
'Py_Chnl_Cd' => config('huishibao.Py_Chnl_Cd'), // 支付渠道代码,默认送25个0
'Ittparty_Tms' => $this->time_ms(), // 发起方时间戳,yyyyMMddHHmmssfff 年月日, 时分秒,毫秒
'Ittparty_Jrnl_No' => CommonRepo::create_uuid(), // 发起方流水号,该笔直连交易的客户方流水号(不允许重复)
'Mkt_Id' => config('huishibao.Mkt_Id'), // 14位市场编号,该字段由银行在正式上线前提供,测试阶段有测试数据
'Main_Ordr_No' => $order_no, // 客户方主订单流水号,不允许重复
'Sub_Appid' => config('huishibao.Sub_Appid'),
'Sub_Openid' => $openid,
// 'Pymd_Cd' => '03', // 支付方式,01 PC端(收银台) 02 线下支付 03 移动端H5页面 (收银台,支持app) 05 微信小程序 06 对私网银 07 聚合二维码 08龙支付 09被扫 11数字电子钱包 12无感支付 13共享钱包 14支付宝小程序
'Pymd_Cd' => '05', // 支付方式,01 PC端(收银台) 02 线下支付 03 移动端H5页面 (收银台,支持app) 05 微信小程序 06 对私网银 07 聚合二维码 08龙支付 09被扫 11数字电子钱包 12无感支付 13共享钱包 14支付宝小程序
'Py_Ordr_Tpcd' => '03', // 订单类型,03在途订单(只有是否支持在途模式为“是”时才可以使用,品类管控市场订单类型必须为03),04普通订单
'Ccy' => '156', // 币种,156人民币
'Ordr_Tamt' => $amount, // 订单总金额
'Txn_Tamt' => $amount, // 交易总金额
'Pay_Dsc' => '在线支付',
'Orderlist' => [ // 订单类型为“04普通订单”时,子订单列表至少要有1条记录,订单类型为“02 消费券购买订单”或“03 在途订单”时,子订单列表固定为1条记录
[
'Mkt_Mrch_Id' => config('huishibao.Mkt_Mrch_Id'), // 商家编号,20位商家编号,该字段由银行在正式上线前提供,测试阶段有测试数据,订单类型为“03在途订单”时,填写市场方商家编号(市场编号+000000)
'Cmdty_Ordr_No' => $order_no, // 客户方子订单编号不允许重复
'Ordr_Amt' => $amount, // 订单商品总金额,即应付金额,所有商品订单金额之和等于主订单金额;
'Txnamt' => $amount, // 消费者实付金额,所有商品订单金额之和等于主交易总金额
]
],
'Vno' => '4', // 版本号,默认填写版本4
];
$res_data = $this->commReq($url, $param);
return $res_data;
}
/**
* 查询订单信息
*
* @param string $order_no
* @return array
*/
public function reqOrderInfQuery($order_no)
{
$url = 'https://xxx/OrderInfQuery';
$param = [
'Ittparty_Stm_Id' => config('huishibao.Ittparty_Stm_Id'), // 发起渠道编号,默认送5个0
'Py_Chnl_Cd' => config('huishibao.Py_Chnl_Cd'), // 支付渠道代码,默认送25个0
'Ittparty_Tms' => $this->time_ms(), // 发起方时间戳,yyyyMMddHHmmssfff 年月日, 时分秒,毫秒
'Ittparty_Jrnl_No' => CommonRepo::create_uuid(), // 发起方流水号,该笔直连交易的客户方流水号(不允许重复)
'Mkt_Id' => config('huishibao.Mkt_Id'), // 14位市场编号,该字段由银行在正式上线前提供,测试阶段有测试数据
'Main_Ordr_No' => $order_no,
'Vno' => '4', // 版本号,默认填写版本4
];
$res_data = $this->commReq($url, $param);
return $res_data;
}
/**
* 确认收货接口
* 1、请避免在0点前后5分钟内进行确认收货。
* 2、本接口不适用于品类管控的市场。
*
* @param string $order_no_huishibao 惠市宝生成的订单编号
* @return array
*/
public function reqMergeNoticeArrival($order_no_huishibao)
{
$url = 'https://xxx/mergeNoticeArrival';
$param = [
'Ittparty_Stm_Id' => config('huishibao.Ittparty_Stm_Id'), // 发起渠道编号,默认送5个0
'Py_Chnl_Cd' => config('huishibao.Py_Chnl_Cd'), // 支付渠道代码,默认送25个0
'Ittparty_Tms' => $this->time_ms(), // 发起方时间戳,yyyyMMddHHmmssfff 年月日, 时分秒,毫秒
'Ittparty_Jrnl_No' => CommonRepo::create_uuid(), // 发起方流水号,该笔直连交易的客户方流水号(不允许重复)
'Mkt_Id' => config('huishibao.Mkt_Id'), // 14位市场编号,该字段由银行在正式上线前提供,测试阶段有测试数据
'Prim_Ordr_No' => $order_no_huishibao, // 惠市宝生成的订单编号
'Vno' => '4', // 填写版本为4
];
$res_data = $this->commReq($url, $param);
return $res_data;
}
/**
* 查询支付结果接口
*
* @param string $order_no
* @return array
*/
public function reqGatherEnquireOrder($order_no)
{
$url = 'https://xxx/gatherEnquireOrder';
$param = [
'Ittparty_Stm_Id' => config('huishibao.Ittparty_Stm_Id'), // 发起渠道编号,默认送5个0
'Py_Chnl_Cd' => config('huishibao.Py_Chnl_Cd'), // 支付渠道代码,默认送25个0
'Ittparty_Tms' => $this->time_ms(), // 发起方时间戳,yyyyMMddHHmmssfff 年月日, 时分秒,毫秒
'Ittparty_Jrnl_No' => CommonRepo::create_uuid(), // 发起方流水号,该笔直连交易的客户方流水号(不允许重复)
'Mkt_Id' => config('huishibao.Mkt_Id'), // 14位市场编号,该字段由银行在正式上线前提供,测试阶段有测试数据
'Main_Ordr_No' => $order_no,
'Vno' => '4', // 版本号,默认填写版本4
];
$res_data = $this->commReq($url, $param);
return $res_data;
}
/**
* 订单全额退款接口
*
* @param string $refund_no 退款流水号
* @param string $order_no_huishibao_flow 惠市宝生成的交易流水号
* @return array
*/
public function reqRefundOrderFull($refund_no, $order_no_huishibao_flow)
{
$url = 'https://xxx/refundOrder';
$param = [
'Ittparty_Stm_Id' => config('huishibao.Ittparty_Stm_Id'), // 发起渠道编号,默认送5个0
'Py_Chnl_Cd' => config('huishibao.Py_Chnl_Cd'), // 支付渠道代码,默认送25个0
'Ittparty_Tms' => $this->time_ms(), // 发起方时间戳,yyyyMMddHHmmssfff 年月日, 时分秒,毫秒
'Ittparty_Jrnl_No' => CommonRepo::create_uuid(), // 发起方流水号,该笔直连交易的客户方流水号(不允许重复)
'Mkt_Id' => config('huishibao.Mkt_Id'), // 14位市场编号,该字段由银行在正式上线前提供,测试阶段有测试数据
'Cust_Rfnd_Trcno' => $refund_no, // 该字段由发起方生成,请求退款时不允许重复(当出现请求超时情况时,客户可凭借此字段重复发起退款,对于同一笔客户方退款流水号,惠市宝确保只发生一次退款)。重复流水号可查询该流水号退款请求结果;不同流水号为发起新请求。
'Py_Trn_No' => $order_no_huishibao_flow, // 惠市宝生成,与该订单的支付动作唯一匹配
'Vno' => '4', // 版本号,默认填写版本4
];
$res_data = $this->commReq($url, $param);
return $res_data;
}
/**
* 订单部分退款接口
*
* @param string $refund_no 退款流水号
* @param string $order_no_huishibao_flow 惠市宝生成的交易流水号
* @param string $order_no_sub 惠市宝生成的子订单编号
* @param string $amount 部分退款金额
* @return array
*/
public function reqRefundOrder($refund_no, $order_no_huishibao_flow, $order_no_sub, $amount)
{
$url = 'https://xxx/refundOrder';
$amount = CommonRepo::returnMoney($amount);
$param = [
'Ittparty_Stm_Id' => config('huishibao.Ittparty_Stm_Id'), // 发起渠道编号,默认送5个0
'Py_Chnl_Cd' => config('huishibao.Py_Chnl_Cd'), // 支付渠道代码,默认送25个0
'Ittparty_Tms' => $this->time_ms(), // 发起方时间戳,yyyyMMddHHmmssfff 年月日, 时分秒,毫秒
'Ittparty_Jrnl_No' => CommonRepo::create_uuid(), // 发起方流水号,该笔直连交易的客户方流水号(不允许重复)
'Mkt_Id' => config('huishibao.Mkt_Id'), // 14位市场编号,该字段由银行在正式上线前提供,测试阶段有测试数据
'Cust_Rfnd_Trcno' => $refund_no, // 该字段由发起方生成,请求退款时不允许重复(当出现请求超时情况时,客户可凭借此字段重复发起退款,对于同一笔客户方退款流水号,惠市宝确保只发生一次退款)。重复流水号可查询该流水号退款请求结果;不同流水号为发起新请求。
'Py_Trn_No' => $order_no_huishibao_flow, // 惠市宝生成,与该订单的支付动作唯一匹配
'Rfnd_Amt' => $amount, // 订单全额退款时不需要送,订单部分退款时必须送此值,且值等于所有子订单的退款金额之和
'Sub_Ordr_List' => [
[
'Sub_Ordr_Id' => $order_no_sub, // 惠市宝生成的子订单编号
'Rfnd_Amt' => $amount,
],
],
'Vno' => '4', // 版本号,默认填写版本4
];
$res_data = $this->commReq($url, $param);
return $res_data;
}
/**
* 分账状态查询接口
*
* @param string $order_no_huishibao_flow 惠市宝生成的交易流水号
* @return array
*/
public function reqSubAccountEnquire($order_no_huishibao_flow)
{
$url = 'https://xxx/subAccountEnquire';
$param = [
'Ittparty_Stm_Id' => config('huishibao.Ittparty_Stm_Id'), // 发起渠道编号,默认送5个0
'Py_Chnl_Cd' => config('huishibao.Py_Chnl_Cd'), // 支付渠道代码,默认送25个0
'Ittparty_Tms' => $this->time_ms(), // 发起方时间戳,yyyyMMddHHmmssfff 年月日, 时分秒,毫秒
'Ittparty_Jrnl_No' => CommonRepo::create_uuid('', false), // 发起方流水号,该笔直连交易的客户方流水号(不允许重复)
'Mkt_Id' => config('huishibao.Mkt_Id'), // 14位市场编号,该字段由银行在正式上线前提供,测试阶段有测试数据
'Py_Trn_No' => $order_no_huishibao_flow,
'Vno' => '5', // 填写版本为4
];
$res_data = $this->commReq($url, $param);
return $res_data;
}
/**
* 在途信息确认接口
*
* @param string $order_no_huishibao_flow 惠市宝生成的交易流水号
* @param array $part_list 分账方列表 [[ 'Seq_No' => 1, 'Mkt_Mrch_Id' => '41060860800392000000', 'Amt' => 1 ]]
* @return array
*/
public function reqConfirmOnTheWay($order_no_huishibao_flow, $part_list)
{
$url = 'https://xxx/confirmOnTheWay';
$param = [
'Ittparty_Stm_Id' => config('huishibao.Ittparty_Stm_Id'), // 发起渠道编号,默认送5个0
'Py_Chnl_Cd' => config('huishibao.Py_Chnl_Cd'), // 支付渠道代码,默认送25个0
'Ittparty_Tms' => $this->time_ms(), // 发起方时间戳,yyyyMMddHHmmssfff 年月日, 时分秒,毫秒
'Ittparty_Jrnl_No' => CommonRepo::create_uuid(), // 发起方流水号,该笔直连交易的客户方流水号(不允许重复)
'Mkt_Id' => config('huishibao.Mkt_Id'), // 14位市场编号,该字段由银行在正式上线前提供,测试阶段有测试数据
'Py_Trn_No' => $order_no_huishibao_flow,
'Parlist' => $part_list,
'Vno' => '3', // 填写版本为3
];
$res_data = $this->commReq($url, $param);
return $res_data;
}
/**
* 返回结果验签
*
* @param string $str_raw
* @param string $string
* @return int
*/
public function valid_encrypt($str_raw, $string)
{
$key = chunk_split(config('huishibao.public_key_bank'), 64, "\n");
$key = "-----BEGIN PUBLIC KEY-----\n" . wordwrap($key) . "-----END PUBLIC KEY-----";
$result = openssl_verify($str_raw, base64_decode($string), $key, OPENSSL_ALGO_SHA256);
return $result;
}
/**
* @return \think\Response
*/
public function res_error()
{
return response('forbid', 401);
}
/**
* @return void
*/
public function res_success()
{
$success_data = [
'Svc_Rsp_St' => '00', // 服务响应状态,00-成功,01-失败
];
CommonRepo::echo_json($success_data);
}
/**
* 写文件
*
* @param string $path
* @param string $content
* @return int|false
*/
public function filePutContent($path, $content, $type = '')
{
$date = date('c');
$content = "[{$date}] [{$type}] {$content}\n";
return file_put_contents($path, $content, FILE_APPEND);
}
/**
* @param array $param
* @return string
*/
public function join_param(array $param)
{
unset($param['Sign_Inf']);
unset($param['Svc_Rsp_St']);
unset($param['Svc_Rsp_Cd']);
unset($param['Rsp_Inf']);
ksort($param);
$str = '';
foreach ($param as $k => $v) {
if ($v !== '') {
if (is_array($v)) {
if (is_array($v[0])) {
foreach ($v as $vv) {
$str .= ($this->join_param($vv) . '&');
}
} else {
$str .= ($this->join_param($v) . '&');
}
} else {
$str .= "$k=$v&";
}
}
}
$str = trim($str, '&');
return $str;
}
/**
* @param string $url
* @param array $param
* @return array
*/
private function commReq($url, $param)
{
$param_str = $this->join_param($param);
$param['Sign_Inf'] = $this->encrypt($param_str); // 签名信息,将上述参数进行拼接并用私钥生成签名
$opt = [
'headers' => [
'Content-Type: application/json; charset=utf-8',
],
];
$res = HttpExtend::post($url, CommonRepo::jsonRet($param), $opt);
$res_data = CommonRepo::jsonDecode($res);
return $res_data;
}
/**
* @param string $str
* @return string
*/
private function encrypt($str)
{
$key = chunk_split(config('huishibao.private_key'), 64, "\n");
$key = "-----BEGIN RSA PRIVATE KEY-----\n" . wordwrap($key) . "-----END RSA PRIVATE KEY-----";
$res = openssl_sign($str, $sign, $key, OPENSSL_ALGO_SHA256);
if (!$res) {
die('sign fail');
}
$sign = base64_encode($sign);
return $sign;
}
/**
* 发起方时间戳,yyyyMMddHHmmssfff 年月日, 时分秒,毫秒
* @return string
*/
private function time_ms()
{
return CommonRepo::timeCut(null, 'no_space') . '000';
}
}
本文来自博客园,作者:imzhi,转载请注明原文链接:https://www.cnblogs.com/imzhi/p/18163791