前言
最近各种支付第三方深受老板喜爱,于是乎我也开始了疯狂对接第三方的旅程。
产品还是丰富,我们使用到了 “聚合支付” 微信支付宝网银都可以+代付业务(付款给银行卡)
一、支付
用支付宝来实例一下,其他方式更换下参数通用
/**
* 汇聚支付
*/
class Joinpay
{
const MCH_NO = "商户号"; // 商户号
/**聚合支付 */
const P0_VERSION = "2.1"; // 聚合支付接口版本号 固定为:2.1
const MS5_BOUND_SYMBOL = "MD5签名密钥"; // 如果是选择的RSA加密就不用这个参数
const QA_TRADEMERCHANTNO = "报备商户号"; // 报备商户号
const PLAT_PUBLIC_KEY = "平台公钥"; // 平台公钥
const MCH_PRIVATE_KEY = "商户私钥"; // 商户私钥
/**
* 支付宝H5 请求忽略请求头
* @param orderNo 订单号
* @param payAmount 付款金额
* @param orderName 商品名称
* @return \think\Response
*/
public function onPayMentByAlipayH5()
{
$url = "https://www.joinpay.com/trade/uniPayApi.action"; // 请求地址
$notifyUrl = "https://.."; // 回调地址
$orderNo = "商家自定义订单号";
$payAmount = "0.01"; // 单位:元,精确到分,保留两位小数
$orderName = "测试商品名称";
$payScenc = "mall"; // 会原封不动的回调回来,可不传我用来做业务场景区分
// 请求参数
$params = [
"p0_Version" => self::P0_VERSION, // 版本号
"p1_MerchantNo" => self::MCH_NO, // 商户号
"p2_OrderNo" => $orderNo, // 自定义订单号
"p3_Amount" => $payAmount, // 支付金额
"p4_Cur" => "1", // 币种 默认1:人民币
"p5_ProductName" => $orderName, // 商品的名称
"p7_Mp" => $payScenc, // 公用回传参数
"p9_NotifyUrl" => $notifyUrl, // 服务器异步通知地址
"q1_FrpCode" => "ALIPAY_H5", // 支付类型 支付宝H5
"qa_TradeMerchantNo" => self::QA_TRADEMERCHANTNO, // 报备商户号
];
// 生成签名
$hmacVal = $this->hmacRequest($params, self::MS5_BOUND_SYMBOL);
$params["hmac"] = $hmacVal;
$result = $this->postJsonSync($url, $params); // 发起请求
$result = json_decode($result, true); // 返回参数数组化
// 请求失败
if ($result["ra_Code"] != 100) {
// 存储失败请求或者其他业务操作
}
// 请求成功:返回参数rc_Result给前端做跳转
$result = $result["rc_Result"];
return $result;
// 贴一下返回示例
{
"r1_MerchantNo": "商户号",
"rd_Pic": "",
"r6_FrpCode": "ALIPAY_H5",
"r7_TrxNo": "平台流水号",
"r0_Version": "2.1",
"r3_Amount": "0.01",
"r4_Cur": "1",
"r2_OrderNo": "商户自定义单号",
"rb_CodeMsg": "",
"hmac": "签名串",
"ra_Code": 100,
"rc_Result": "
<html><head><meta http-equiv='Content-Type'content='text/html; charset=UTF-8'><title></title></head><body><script type='text/javascript'>location.href='https://qr.alipay.com/***';</script></body></html>"
}
}
// ______________顺道贴一下出款 需要自取
/**
* 代付 请求需要请求头
* @param url 单笔代付接口
*/
public function singlePay()
{
$url = "https://www.joinpay.com/payment/pay/singlePay"; // 请求地址
$notifyUrl = "https://.."; // 回调地址
$orderNo = "商户自定义单号";
$accountNo = "收款人账号";
$nameEnc = "收款人姓名";
$paidAmount = "0.01"; // 单位:元,精确到分,保留两位小数。
$params = [
"userNo" => self::MCH_NO,
"productCode" => "BANK_PAY_DAILY_ORDER", // 产品类型:朝夕付5分钟到
"requestTime" => date("Y-m-d H:i:s"), // 交易请求时间
"merchantOrderNo" => $orderNo, // 商户订单号
"receiverAccountNoEnc" => $accountNo, // 银行收款账号
"receiverNameEnc" => $nameEnc, // 持卡人姓名
"receiverAccountType" => 201, // 账户类型 私201 公204
"paidAmount" => $paidAmount, // 交易金额
"currency" => "201", // 人民币币种填写:201
"isChecked" => "202", // 是否复核 是201 否202
"paidDesc" => "测试出款", // 代付用途
"paidUse" => "211", // 代付用途 211:消费款项
"callbackUrl" => $notifyUrl // 回调地址
];
// 生成签名
$hmacVal = $this->hmacRequest($params, self::MS5_BOUND_SYMBOL);
$params["hmac"] = $hmacVal;
$result = $this->postJsonSync($url, $params, true); // 发起请求
$result = json_decode($result, true); // 返回参数数组化
// 受理成功
return $result["message"];
// 贴一下返回示例
{
"data": {
"errorCode": "",
"errorDesc": "",
"userNo": "商户号",
"merchantOrderNo": "商户订单号",
"hmac": "签名串"
},
"statusCode": 2001,
"message": "受理成功"
}
}
/**
* 生成签名
* @param $params
* @param $key
* @param string $encryptType 签名类型2=RSA 1=MD5
* @return string
*/
function hmacRequest($params, $key, $encryptType = "1")
{
if ("1" == $encryptType) {
// MD5:key = md5 签名密钥
return md5(implode("", $params) . $key);
} else {
// RSA:key = 商户私钥
$str = chunk_split($key, 64, "\n");
$key = "-----BEGIN RSA PRIVATE KEY-----\n$str-----END RSA PRIVATE KEY-----\n";
$signature = '';
$params = implode('', $params);
openssl_sign($params, $signature, $key, OPENSSL_ALGO_MD5);
$sign = base64_encode($signature);
return $sign;
}
}
/**
* POST请求
* @param url 请求地址
* @param params 请求数据
* @param contentType 是否携带请求头
*/
function postJsonSync($url, $params, $contentType = false)
{
if (function_exists("curl_init")) { // curl方式
$oCurl = curl_init();
if (stripos($url, "https://") !== FALSE) {
curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, FALSE);
}
$string = $params;
if (is_array($params)) {
$aPOST = array();
foreach ($params as $key => $val) {
$aPOST[] = $key . "=" . urlencode($val);
}
$string = join("&", $aPOST);
}
curl_setopt($oCurl, CURLOPT_URL, $url);
curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($oCurl, CURLOPT_POST, TRUE);
//$contentType json处理
if ($contentType) {
$headers = array(
"Content-type: application/json;charset='utf-8'",
);
curl_setopt($oCurl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($oCurl, CURLOPT_POSTFIELDS, json_encode($params));
} else {
curl_setopt($oCurl, CURLOPT_POSTFIELDS, $string);
}
$response = curl_exec($oCurl);
curl_close($oCurl);
return $response;
// return json_decode($response, true);
} elseif (function_exists("stream_context_create")) { // php5.3以上
$opts = array(
"http" => array(
"method" => "POST",
"header" => "Content-type: application/x-www-form-urlencoded",
"content" => http_build_query($params),
)
);
$_opts = stream_context_get_params(stream_context_get_default());
$context = stream_context_create(array_merge_recursive($_opts["options"], $opts));
return file_get_contents($url, false, $context);
// return json_decode(file_get_contents($url, false, $context), true);
} else {
return FALSE;
}
}
}
二、回调
/**
* @method 汇聚支付回调:GET
* @param r2_OrderNo 商户提供的自定义订单号
* @param r3_Amount 支付金额
* @param r5_Mp 公共响应参数:业务场景
* @param r6_Status 支付状态 100:成功 101:失败
* @param r7_TrxNo 支付平台生成的交易流水号
* @param ra_PayTime 支付时间
*/
public function JoinPayNotifyUrl()
{
$r2_OrderNo = $_GET["r2_OrderNo"];
$r3_Amount = $_GET["r3_Amount"];
$r5_Mp = $_GET["r5_Mp"];
$r6_Status = $_GET["r6_Status"];
$r7_TrxNo = $_GET["r7_TrxNo"];
$ra_PayTime = $_GET["ra_PayTime"];
$ra_PayTime = urldecode(urldecode($ra_PayTime));
if ($r6_Status == 100) {
// 成功
} else {
// 失败
}
// 返回给汇聚支付
echo "success";
// 贴一下回调数据:回调格式需要$_GET获取,时间需要两次urldecode
"https://www.baidu.com?
r1_MerchantNo=888000000000000
&r2_OrderNo=2020100000000000000
&r3_Amount=10.00
&r4_Cur=1
&r5_Mp=goods
&r6_Status=100
&r7_TrxNo=100220100000000000
&r8_BankOrderNo=100220100000000000
&r9_BankTrxNo=4200000000202000000000000000
&ra_PayTime=2022-08-11%2B16%253A14%253A39
&rb_DealTime=2022-08-11%2B16%253A14%253A39
&rc_BankCode=WEIXI";
}
// ______________顺道贴一下出款回调 需要自取
/**
* 单笔代付回调:POST
*/
public function singlePayNotify()
{
// 获取通知的数据
$postJsonData = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : file_get_contents("php://input");
// 转换数组
$aParams = json_decode($postJsonData, true);
if ($aParams["status"] == 205) {
// 代付成功
}else{
// 代付失败
}
// 返回给汇聚支付
$result = [
"statusCode" => "2001",
"message" => "成功"
];
return $result;
// 贴一下回调数据
{
"errorCode":"",
"errorCodeDesc":"",
"fee":1,
"hmac":"签名串",
"merchantOrderNo":"订单号",
"paidAmount":0.01,
"platformSerialNo":"平台流水号",
"receiverAccountNoEnc":"收款账号",
"receiverNameEnc":"姓名",
"status":205,
"userNo":"商户号"
}
}
总结
支付包含了“聚合支付”+“代付业务”,两个方法请求方式需要区分一下是否需要请求头,回调方式也不一样需要区分一下,其他 微信,扫码,公众号支付等根据文档请求调整参数就好