jh-admin/addon/cypay/model/RequestApi.php

252 lines
12 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* SaaSMall商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 成都SAAS云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.gobuysaas.com
* =========================================================
*/
namespace addon\cypay\model;
use addon\weapp\model\Config as weAppConfig;
use app\model\BaseModel;
use think\exception\ValidateException;
class RequestApi extends BaseModel
{
// 接口请求地址:正式环境=https://pay.chanpay.com/merchant/gateway测试环境=https://cpay.chanpay.com/merchant/gateway
private string $apiLink = 'https://pay.chanpay.com/merchant/gateway';// 正式环境
private string $institutionNumber = '49072480';// 合作机构号
private string $productCode = '1000';// 营销产品编码,由畅捷支付分配
// 基础产品编码,由畅捷支付分配
private array $functionCode = [
'chanpay.merchanttrade.weixin.appletpay' => '1000140001',// 微信小程序
// '' => '1000100003',// 付款码-银联-借记
// '' => '1000100003',// 付款码-银联-贷记
// '' => '1000100002',// 付款码-支付宝
// '' => '1000110003',// 扫码-银联-借记
// '' => '1000110003',// 扫码-银联-贷记
// '' => '1000340005',// 分账
// '' => '1000110001',// 扫码-微信
'chanpay.merchanttrade.appletpay.cashier' => '1000160001',// 微信小程序收银台
// '' => '1000160002',// 支付宝小程序收银台
];
// 畅捷公钥 RSA
private string $publicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCQedhgpTUxuWDof5uiHWszPP/462Q/ORos8uV11g8nYmchcyE3x8jOXE5ZKRAua5HUDNkLQG/8wu4+tPVicKe3r9DOefZf+zxZgHB/uddA+Sl54h9BzjPB8RscBtDM2DWRZhdnVu4LMRb9Lp9eRYTLbviPazCEm13FqttHT35oAQIDAQAB';
// 畅捷公钥 RSA2
private string $publicKeyTwo = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsNU7PbTNvy16IF5sjzMxS3wQo0kvkq3iNmIIbcLnhatlbdeqdTG+P4wnSM+28Eums/izjL2TKdshoPcuvZ18/rGOUprCeeL7VfTtKu/mlS5H+FCXkdG0a0kstvjloqwRcksV2IiAiFttdB85zI4stu4NBMh4oFd5+nO8Jt7JMPI1J/4zd6VGn4bJ6DEcKVfXn+xpZ9fp0LRRREB5AbqJKpSLS7G+cQE1YT9kRHnAvCZcE+WPwwv24lIOiEXcNacz1vuDC4kZf3ahweuHAGlWve00/O9iIzSkB0FazUGLjOf6WcQiugEz1DtL8wKW2OlAwuk8VU3sSuLbDmzLdYG84QIDAQAB';
// 配置信息
private $config;
public function __construct($siteId)
{
// 配置获取
$this->config = (new Config())->getConfig($siteId);
}
/**
* Common: 请求发送
* Author: wu-hui
* Time: 2024/07/23 13:32
* @param string $method
* @param array $bizContent
* @param string $apiLink
* @return array
*/
private function requestApi(string $method, array $bizContent, string $apiLink = '')
{
try {
// 判断:如果不存在指定请求地址 使用默认地址
if (!$apiLink) $apiLink = $this->apiLink;
// 处理请求内容
$bizContent = $this->handleBizContent($bizContent);
// 请求数组
$data = [
'method' => $method,// 请求接口
'acq_sp_id' => $this->institutionNumber,// 合作机构号,由畅捷支付分配
'product_code' => $this->productCode,// 营销产品编码,由畅捷支付分配
'function_code' => $this->functionCode[$method],// 基础产品编码,由畅捷支付分配 商户管理-商户维护-商户详情
'format' => 'JSON',
'charset' => 'UTF-8',
'sign_type' => 'RSA2',
'timestamp' => date("YmdHis"),
'version' => '1.0',
'biz_content' => $bizContent
];
var_dump($apiLink, $data);
return 1111;
$data['sign'] = $this->getSign($data);
// 发起请求
$result = curlPost($apiLink, $data);
// 结果处理
if ($result['sub_code'] == 'FAIL') {
throw new ValidateException($result['sub_msg']);
} else {
// 返回成功 信息解密
$content = $result['content'] ?? [];
if ($content) $content = $this->handleResultContent($content);
return $this->success($content);
}
} catch (\Exception $e) {
trace(['msg' => $e->getMessage()], '好收银 - 接口请求错误');
return $this->error([], $e->getMessage());
}
}
/**
* Common: 请求数据主要参数加密
* Author: wu-hui
* Time: 2024/07/22 14:44
* @param $bizContent
* @return string
*/
private function handleBizContent($bizContent)
{
// 基本参数
$bizContentJson = json_encode($bizContent);
$publicKey = "-----BEGIN PUBLIC KEY-----\n" . trim($this->publicKeyTwo) . "\n-----END PUBLIC KEY-----";
// 获取秘钥详细信息
if (strlen($bizContentJson) > 255) {
// 加密每段最大245解密每段最大256
$bizContentArray = mb_str_split($bizContentJson, 245, 'UTF-8');
$useBizContent = '';
foreach ($bizContentArray as $bizContentString) {
openssl_public_encrypt($bizContentString, $encryptedChunk, $publicKey);
$useBizContent .= $encryptedChunk;
}
} else {
openssl_public_encrypt($bizContentJson, $useBizContent, $publicKey);
}
return base64_encode($useBizContent);
}
/**
* Common: 生成签名
* Author: wu-hui
* Time: 2024/07/22 16:04
* @param $data
* @return string
*/
private function getSign($data)
{
// 请求参数转字符串
$signStr = 'method' . '=' . $data['method'] . '&';
$signStr .= 'acq_sp_id' . '=' . $this->institutionNumber . '&';
$signStr .= 'function_code' . '=' . $data['function_code'] . '&';
$signStr .= 'product_code' . '=' . $data['product_code'] . '&';
$signStr .= 'biz_content' . '=' . $data['biz_content'];
$signStr = trim($signStr, '&');
// 生成签名
$privateKey = "-----BEGIN RSA PRIVATE KEY-----\n" . $this->config['private_key'] . "\n-----END RSA PRIVATE KEY-----";
$key = openssl_get_privatekey($privateKey);
openssl_sign($signStr, $signature, $key, "SHA256");
return base64_encode($signature);
}
/**
* Common: 返回数据解密
* Author: wu-hui
* Time: 2024/07/23 11:51
* @param $content
* @return array|mixed
*/
public function handleResultContent($content)
{
// 私钥信息
$privateKey = "-----BEGIN RSA PRIVATE KEY-----\n" . $this->config['private_key'] . "\n-----END RSA PRIVATE KEY-----";
$privateKey = openssl_get_privatekey($privateKey);
// 信息解密
$bizContentArray = str_split(base64_decode($content), 256);
$content = '';
foreach ($bizContentArray as $bizContentString) {
openssl_private_decrypt($bizContentString, $decrypted, $privateKey, OPENSSL_PKCS1_PADDING);
$content .= $decrypted;
}
return is_json($content) ? json_decode($content, true) : [];
}
// 异步通知 签名验证
public function signValidate($params)
{
// 是否开启收银台
$isUseCashier = $this->config['is_isppay'] ?? 0;
$data = [
'function_code' => $params['function_code'],
'product_code' => $params['product_code'],
'biz_content' => $params['biz_content'],
];
if ($isUseCashier == 1) $data['method'] = 'chanpay.merchanttrade.appletpay.cashier';
else $data['method'] = 'chanpay.merchanttrade.weixin.appletpay';
$sign = $this->getSign($data);
// debug([
// 'sign' => $sign,
// 'noti' => $params['sign']
// ]);
return true;//$sign == $params['sign'];
}
/**
* Common: 微信小程序支付 - 创建支付
* Author: wu-hui
* Time: 2024/07/23 13:31
* @param $params
* @return array
*/
public function getWeAppPayInfo($params)
{
$isUseCashier = $this->config['is_cashier'] ?? 0;
// 小程序支付 公共请求参数生成
$outTradeNo = $params['out_trade_no'] ?? '';
$outTradeNo = $outTradeNo . '_' . rand(1000, 9999);
$bizContent = [
'merchant_id' => $this->config['mch_id'],// 商户编号,由畅捷支付分配
'out_trade_no' => $outTradeNo,// 商户订单号商户系统的内部订单号。5~32个字符、可包含字母、数字、下划线商户系统需保证不重复
// 'total_amount' => (int)sprintf("%.0f", $params['pay_money'] * 100),// 订单总金额,单位为分,取值范围[1,10000000000],不允许包含任何文字、符号
'total_amount' => 10,// 订单总金额,单位为分,取值范围[1,10000000000],不允许包含任何文字、符号
'body' => $params['pay_body'],// 商品描述,订单的标题信息,鉴于风控等因素,建议该字段严格按照规范传递,可参见【参数规定】
// 'goods_tag' => '',// 订单优惠标记,代金券或立减优惠功能的参数
// 'attach' => '',// 订单附加数据该字段主要用于商户携带订单的自定义数据在查询API和支付通知中原样返回
// 'limit_credit_pay' => '',// 是否限制信用卡限定用户使用时能否使用信用卡值为1=禁用信用卡;值为0或者不传此参数则不禁用
'mch_create_ip' => $params['mch_create_ip']??"127.0.0.1",// 终端IP支持IPV4和IPV6两种格式的IP地址。调用API的机器IP
// 'device_info' => '',// 终端序列号,收银设备的唯一产品序列号(SN) ,多用于鉴别交易场景、风控合规等因素
// 'op_shop_id' => '',// 门店编号,由商户自定义,若有门店则必传
// 'op_user_id' => '',// 收银员,操作员帐号,或者默认为商户号
// 'need_receipt' => '',// 电子发票【微信】需要和微信公众平台的发票功能联合传入Y时微信支付成功消息和支付详情页将出现开票入口
// 'time_start' => '',// 订单生成时间格式为yyyymmddhhmmss该时间取自商户服务器。备注:订单生成时间与超时时间需要同时传入才会生效。
// 'time_expire' => '',// 订单超时/时间格式为yyyymmddhhmmss该时间取自商户服务器。备注:订单生成时间与超时时间需要同时传入才会生效
'notify_url' => $params['notify_url'],// 异步通知地址
];
// 根据是否开启收银台 进行对应的操作
if ($isUseCashier == 1) {
// 启用收银台
$result = $this->requestApi('chanpay.merchanttrade.appletpay.cashier', $bizContent);
return $result;
$result['data']['is_cashier'] = 1;
} else {
// 未启用收银台
$weAppConfig = (new weAppConfig())->getWeappConfig($params['site_id'])['data']['value'];
// 参数补齐
$bizContent['sub_openid'] = $params['sub_openid'];// 子用户标识此参数为微信用户在商户对应sub_appid下的唯一标识
$bizContent['sub_appid'] = $weAppConfig['appid'] ?? '';// 子用户标识此参数为微信用户在商户对应sub_appid下的唯一标识
$result = $this->requestApi('chanpay.merchanttrade.weixin.appletpay', $bizContent);
$result['data']['is_cashier'] = 0;
}
return $result ?? [];
}
}