Files
midi-php/extend/Yzh/YunPay.php
2025-09-17 10:30:17 +08:00

383 lines
21 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
namespace Yzh;
use think\Log;
use Yzh\Config; // 确保该类文件已被正确引入或自动加载
use Yzh\BaseClient;
use Yzh\Model\Apiusersign\ApiUserSignContractRequest;
use Yzh\Model\Apiusersign\ApiUserSignReleaseRequest;
use Yzh\Model\Apiusersign\ApiUserSignRequest;
use Yzh\Model\Apiusersign\GetApiUserSignStatusRequest;
use Yzh\Model\Payment\CreateAlipayOrderRequest;
use Yzh\Model\Payment\CreateBankpayOrderRequest;
use Yzh\Model\Payment\CreateWxpayOrderRequest;
use Yzh\Model\Notify\NotifyRequest;
use Yzh\NotifyClient;
class YunPay
{
public $order_id;
public $real_name;
public $id_card;
public $card_no;
public $order_amount;
public $notify_url = 'https://md.xscmmidi.site/api/Payment/yun_callback';
public $phone = '';
public $config;
public $remark = '';
public $sys_config;
public function __construct($order_id="", $real_name="", $id_card="", $card_no="", $order_amount="", $phone="")
{
//读取配置
$this->sys_config = new SysConfig();
$this->order_id = $order_id;
$this->real_name = $real_name;
$this->id_card = $id_card;
$this->card_no = $card_no;
$this->order_amount = $order_amount;
$this->phone = $phone;
//读取配置
$this->config = Config::newFromArray(array(
'app_dealer_id' => $this->sys_config->dealer_id,
'app_broker_id' => $this->sys_config->broker_id,
'app_key' => $this->sys_config->app_key,
'app_des3_key' => $this->sys_config->des3_key,
'app_private_key' => $this->sys_config->private_key,
'yzh_public_key' => $this->sys_config->public_key,
'sign_type' => $this->sys_config->sign_type
));
}
public function alipay(){
try {
$this->paymentClient = new PaymentClient($this->config);
$this->paymentClient->setEnv(PaymentClient::ENV_PROD);
} catch (\Exception $e) {
return ['code' => 0, 'msg' => $e->getMessage(), 'data' => null];
}
$request = new CreateAlipayOrderRequest(array(
'order_id' => $this->order_id, // 平台企业订单号,由平台企业保持唯⼀性 ,至多支持 64 个英⽂字符
'dealer_id' => $this->sys_config->dealer_id, // 平台企业 ID
'broker_id' => $this->sys_config->broker_id, // 综合服务主体 ID
'real_name' => $this->real_name, // 姓名
'card_no' => $this->card_no, // 收款⼈⽀付宝账户
'id_card' => $this->id_card, // 身份证号码(必填,报税时使用)
'phone_no' => $this->phone, // ⽤户⼿机号
'pay' => $this->order_amount, // 订单⾦额(参数类型是 string单位为元支持两位小数必填
'pay_remark' => $this->remark, // 订单备注(选填,至多支持 40 个字符且不支持特殊字符,⼀个汉字占 2 个字符,不支持的特殊字符为 ' " & | @% ( ) - : # + / < > ¥ \ ,
'check_name' => 'Check', // 校验⽀付宝账户姓名(固定值 Check
'notify_url' => $this->notify_url, // 回调地址(选填,长度不超过 200 个字符)
'project_id' => '' // 项目ID该字段由云账户分配当接口指定项目时会将订单关联指定项目
));
/*
* request-id请求 ID请求的唯一标识
* 建议平台企业自定义 request-id并记录在日志中便于问题发现及排查
* 如未自定义 request-id将使用 SDK 中的 random 方法自动生成。注意random 方法生成的 request-id 不能保证全局唯一,推荐自定义 request-id
*/
$request_id = "requestId".$this->order_id.time().rand(100000,999999).UniqId();
$request->setRequestID($request_id);
$response = $this->paymentClient->createAlipayOrder($request);
if ($response->isSuccess()) {
// TODO 操作成功,支付结果未知,等待异步通知或订单查询接口获取订单状态
return ['code' => 1, 'msg' => '接单成功', 'data' => null];
} elseif ($response->getCode() == '2002') {
// TODO 幂等性校验,订单号已存在,具体订单结果需等待异步通知,或主动调用订单查询接口获取
return ['code' => 0, 'msg' => '订单已存在', 'data' => null];
} else {
// TODO 失败返回,根据返回的 message 处理订单请求,切记若需重试请求,请使用原订单号重试
return ['code' => $response->getCode(), 'msg' => $response->getMessage(). ' request-id:' . $response->getRequestID(), 'data' => null];
}
}
public function Wxpay($wx_openid)
{
try {
$this->paymentClient = new PaymentClient($this->config);
$this->paymentClient->setEnv(PaymentClient::ENV_PROD);
} catch (\Exception $e) {
return ['code' => 0, 'msg' => $e->getMessage(), 'data' => null];
}
$request = new CreateWxpayOrderRequest(array(
'order_id' => $this->order_id, // 平台企业订单号,由平台企业保持唯⼀性,至多支持 64 个英⽂字符
'dealer_id' => $this->sys_config->dealer_id, // 平台企业 ID
'broker_id' => $this->sys_config->broker_id, // 综合服务主体 ID
'real_name' => $this->real_name, // 姓名
'openid' => $wx_openid, // 平台企业 AppID 下⽤户的 openid
'id_card' => $this->card_no, // 身份证号码(必填,报税时使用)
'phone_no' => $this->phone, // ⽤户⼿机号
'pay' => $this->order_amount, // 订单⾦额(参数类型是 string单位为元支持两位小数必填
'pay_remark' => $this->remark, // 订单备注(选填,至多支持 32 个字符且不支持特殊字符,⼀个汉字占 2 个字符,不支持的特殊字符为 ' " & | @% ( ) - : # + / < > ¥ \ ,
'wx_app_id' => '', // 平台企业微信 AppID选填最⼤⻓度为 200若平台企业在云账户绑定了多个 AppID则此处需指定 AppID
'notify_url' => $this->notify_url, // 回调地址(选填,长度不超过 200 个字符)
'wxpay_mode' => 'transfer', // 微信支付模式必填固定值transfer
'project_id' => '' // 项目 ID该字段由云账户分配当接口指定项目时会将订单关联指定项目
));
/*
* request-id请求 ID请求的唯一标识
* 建议平台企业自定义 request-id并记录在日志中便于问题发现及排查
* 如未自定义 request-id将使用 SDK 中的 random 方法自动生成。注意random 方法生成的 request-id 不能保证全局唯一,推荐自定义 request-id
*/
$request_id = "requestId".$this->order_id.time().rand(100000,999999).UniqId();
$request->setRequestID($request_id);
$response = $this->paymentClient->createWxpayOrder($request);
if ($response->isSuccess()) {
// TODO 操作成功,支付结果未知,等待异步通知或订单查询接口获取订单状态
return ['code' => 1, 'msg' => '接单成功', 'data' => null];
} elseif ($response->getCode() == '2002') {
// TODO 幂等性校验,订单号已存在,具体订单结果需等待异步通知,或主动调用订单查询接口获取
return ['code' => 0, 'msg' => '订单已存在', 'data' => null];
} else {
// TODO 失败返回,根据返回的 message 处理订单请求,切记若需重试请求,请使用原订单号重试
return ['code' => $response->getCode(), 'msg' => $response->getMessage(). ' request-id:' . $response->getRequestID(), 'data' => null];
}
}
public function bank()
{
try {
$this->paymentClient = new PaymentClient($this->config);
$this->paymentClient->setEnv(PaymentClient::ENV_PROD);
} catch (\Exception $e) {
return ['code' => 0, 'msg' => $e->getMessage(), 'data' => null];
}
// 银行卡实时支付
$request = new CreateBankpayOrderRequest(array(
'order_id' => $this->order_id,
'dealer_id' => $this->sys_config->dealer_id, // 平台企业 ID
'broker_id' => $this->sys_config->broker_id, // 综合服务主体 ID
'real_name' => $this->real_name,
'card_no' => $this->id_card,
'id_card' => $this->card_no,
'phone_no' => $this->phone,
'pay' => $this->order_amount,
'pay_remark' => $this->remark,
'notify_url' => $this->notify_url,
'project_id' => ''
));
$request_id = "requestId".$this->order_id.time().rand(100000,999999).UniqId();
$request->setRequestID($request_id);
$response = $this->paymentClient->createBankpayOrder($request);
if ($response->isSuccess()) {
// TODO 操作成功,支付结果未知,等待异步通知或订单查询接口获取订单状态
return ['code' => 1, 'msg' => '接单成功', 'data' => null];
} elseif ($response->getCode() == '2002') {
// TODO 幂等性校验,订单号已存在,具体订单结果需等待异步通知,或主动调用订单查询接口获取;
return ['code' => 0, 'msg' => '订单已存在', 'data' => null];
} else {
// TODO 失败返回,根据返回的 message 处理订单请求,切记若需重试请求,请使用原订单号重试
return ['code' => $response->getCode(), 'msg' => $response->getMessage(). ' request-id:' . $response->getRequestID(), 'data' => null];
}
}
/*
* 订单状态查询
*/
public function queryOrder($type){
try {
$this->paymentClient = new PaymentClient($this->config);
$this->paymentClient->setEnv(PaymentClient::ENV_PROD);
} catch (\Exception $e) {
return ['code' => 0, 'msg' => $e->getMessage(), 'data' => null];
}
if($type == 1){
$channel = '微信';
}elseif($type == 2){
$channel = '支付宝';
}else{
$channel = '银行卡';
}
// 查询单笔订单信息
$request = new \Yzh\Model\Payment\GetOrderRequest(array(
'order_id' => $this->order_id, // 平台企业订单号,由平台企业保持唯⼀性
'channel' => $channel, // 支付路径名,银⾏卡,⽀付宝,微信(选填,不填默认为银⾏卡订单查询,注意 value 值为中文字符)
'data_type' => '', // 如果为 encryption则对返回的 data 进行加密
));
/*
* request-id请求 ID请求的唯一标识
* 建议平台企业自定义 request-id并记录在日志中便于问题发现及排查
* 如未自定义 request-id将使用 SDK 中的 random 方法自动生成。注意random 方法生成的 request-id 不能保证全局唯一,推荐自定义 request-id
*/
$request_id = "requestId".$this->order_id.time().rand(100000,999999).UniqId();
$request->setRequestID($request_id);
$response = $this->paymentClient->getOrder($request);
if ($response->isSuccess()) {
// TODO 订单查询操作成功,根据订单状态 status 判断订单状态,做业务订单的处理
if($response->getData()->getStatusDetail() == 0){
return ['code' => 1, 'msg' => "订单状态:" . $response->getData()->getStatusMessage(), 'data' => [
'code' => $response->getData()->getStatusDetail(),
'msg' => $response->getData()->getStatusMessage(),
]];
}else{
return ['code' => 1, 'msg' => "订单状态:" . $response->getData()->getStatusDetailMessage(), 'data' => [
'code' => $response->getData()->getStatusDetail(),
'msg' => $response->getData()->getStatusDetailMessage(),
]];
}
} else if ($response->getCode() == '2018') {
// TODO 订单不存在,检查一下 channel 是否传递正确,若正确,则可以使用原 order_id 再次下单
return ['code' => 0, 'msg' => "订单不存在", 'data' => null];
} else {
// TODO 失败返回,其他 code 应当做异常情况,订单状态当“未知”处理,可稍后重试直至获取到 code=0000 或 2018或者是联系云账户进行人工查询
return ['code' => $response->getCode(), 'msg' => $response->getMessage() . ' request-id:' . $response->getRequestID(), 'data' => null];
}
}
/*
* 回调接口处理
*/
public function yun_callback($data,$mess,$timestamp,$sign){
$notifyClient = new NotifyClient($this->config);
// 异步回调参数
$notifyReq = new NotifyRequest ($data, $mess, $timestamp, $sign) ;// 发起验签解密
try {
$result = $notifyClient->verifyAndDecrypt($notifyReq) ;
Log::record("云账户回调信息-返回:".json_encode($result),"info");
$result = json_decode($result,true);
if ($result['signRes']) {
// 验签通过、解密成功
return ['code' => 1, 'msg' => "验签通过、解密成功:", 'data' => $result['data']];
}else{
return ['code' => 0, 'msg' => "验签失败", 'data' => $result['data']];
}
}
catch(Exception $e){
// 发生异常
return ['code' => 0, 'msg' => $e->getMessage (), 'data' => null];
}
}
/*
* 获取协议预览 URL
*/
public function getAgreementPreviewUrl(){
try {
$this->ApiUserSignServiceClient = new ApiUserSignServiceClient($this->config);
$this->ApiUserSignServiceClient->setEnv(ApiUserSignServiceClient::ENV_PROD);
} catch (\Exception $e) {
return ['code' => 0, 'msg' => $e->getMessage(), 'data' => null];
}
$request = new ApiUserSignContractRequest(array(
'dealer_id' => $this->sys_config->dealer_id, // 平台企业 ID
'broker_id' => $this->sys_config->broker_id, // 综合服务主体 ID
));
/*
* request-id请求 ID请求的唯一标识
* 建议平台企业自定义 request-id并记录在日志中便于问题发现及排查
* 如未自定义 request-id将使用 SDK 中的 random 方法自动生成。注意random 方法生成的 request-id 不能保证全局唯一,推荐自定义 request-id
*/
$request_id = "requestId".$this->order_id.time().rand(100000,999999).UniqId();
$request->setRequestID($request_id);
$response = $this->ApiUserSignServiceClient->apiUserSignContract($request);
if ($response->isSuccess()) {
// TODO 获取协议预览 URL 操作成功
return ['code' => 1, 'msg' => "获取协议预览 URL 操作成功", 'data' => [
'url' => $response->getData()->getUrl(),
'title' => $response->getData()->getTitle(),
]];
}else{
return ['code' => 0, 'msg' => "获取协议预览 URL 操作失败", 'data' => null];
}
}
/*
* 用户签约
*/
public function apiUserSign($real_name,$id_card){
try {
$this->ApiUserSignServiceClient = new ApiUserSignServiceClient($this->config);
$this->ApiUserSignServiceClient->setEnv(ApiUserSignServiceClient::ENV_PROD);
} catch (\Exception $e) {
return ['code' => 0, 'msg' => $e->getMessage(), 'data' => null];
}
// 配置请求参数
$request = new ApiUserSignRequest(array(
'dealer_id' => $this->sys_config->dealer_id, // 平台企业 ID
'broker_id' => $this->sys_config->broker_id, // 综合服务主体 ID
"real_name" => $real_name,
"id_card" => $id_card,
"card_type" => "idcard",
));
/*
* request-id请求 ID请求的唯一标识
* 建议平台企业自定义 request-id并记录在日志中便于问题发现及排查
* 如未自定义 request-id将使用 SDK 中的 random 方法自动生成。注意random 方法生成的 request-id 不能保证全局唯一,推荐自定义 request-id
*/
$request_id = "requestId".$this->order_id.time().rand(100000,999999).UniqId();
$request->setRequestID($request_id);
$response = $this->ApiUserSignServiceClient->apiUserSign($request);
if ($response->isSuccess()) {
// TODO 用户签约操作成功
return ['code' => 1, 'msg' => "用户签约操作成功", 'data' => ['request_id' => $request_id]];
}else{
return ['code' => 0, 'msg' => "用户签约操作失败:".$response->getMessage(), 'data' => null];
}
}
/**
* 获取用户签约状态
*/
public function getApiUserSignStatus($real_name,$id_card){
try {
$this->ApiUserSignServiceClient = new ApiUserSignServiceClient($this->config);
$this->ApiUserSignServiceClient->setEnv(ApiUserSignServiceClient::ENV_PROD);
} catch (\Exception $e) {
return ['code' => 0, 'msg' => $e->getMessage(), 'data' => null];
}
// 配置请求参数
$request = new GetApiUserSignStatusRequest(array(
'dealer_id' => $this->sys_config->dealer_id, // 平台企业 ID
'broker_id' => $this->sys_config->broker_id, // 综合服务主体 ID
"real_name" => $real_name,
"id_card" => $id_card
));
/*
* request-id请求 ID请求的唯一标识
* 建议平台企业自定义 request-id并记录在日志中便于问题发现及排查
* 如未自定义 request-id将使用 SDK 中的 random 方法自动生成。注意random 方法生成的 request-id 不能保证全局唯一,推荐自定义 request-id
*/
$request_id = "requestId".$this->order_id.time().rand(100000,999999).UniqId();
$request->setRequestID($request_id);
$response = $this->ApiUserSignServiceClient->getApiUserSignStatus($request);
if ($response->isSuccess()) {
// TODO 用户签约操作成功
return ['code' => 1, 'msg' => "用户签约状态查询", 'data' =>
[
'sign_status' => $response->getData()->getStatus(),
'sign_time' => $response->getData()->getSignedAt(),
]];
}else{
return ['code' => 0, 'msg' => "用户签约状态查询:".$response->getMessage(), 'data' => null];
}
}
/**
* 用户解约
*/
public function unSignYunAccount($real_name,$id_card){
try {
$this->ApiUserSignServiceClient = new ApiUserSignServiceClient($this->config);
$this->ApiUserSignServiceClient->setEnv(ApiUserSignServiceClient::ENV_PROD);
} catch (\Exception $e) {
return ['code' => 0, 'msg' => $e->getMessage(), 'data' => null];
}
// 配置请求参数
$request = new ApiUserSignReleaseRequest(array(
'dealer_id' => $this->sys_config->dealer_id, // 平台企业 ID
'broker_id' => $this->sys_config->broker_id, // 综合服务主体 ID
"real_name" => $real_name,
"id_card" => $id_card,
"card_type" => "idcard",
));
/*
* request-id请求 ID请求的唯一标识
* 建议平台企业自定义 request-id并记录在日志中便于问题发现及排查
* 如未自定义 request-id将使用 SDK 中的 random 方法自动生成。注意random 方法生成的 request-id 不能保证全局唯一,推荐自定义 request-id
*/
$request_id = "requestId".$this->order_id.time().rand(100000,999999).UniqId();
$request->setRequestID($request_id);
$response = $this->ApiUserSignServiceClient->apiUserSignRelease($request);
if ($response->isSuccess()) {
// TODO 用户签约操作成功
return ['code' => 1, 'msg' => "用户解约操作成功", 'data' => ['request_id' => $request_id]];
}else{
return ['code' => 0, 'msg' => "用户解约操作失败:".$response->getMessage(), 'data' => null];
}
}
}