官方提供的代碼包,只有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';
}
}