manghe/app/common/server/platform/AppPlatform.php
2025-07-09 12:56:11 +08:00

323 lines
13 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 app\common\server\platform;
use Alipay\EasySDK\Kernel\Factory;
use Alipay\EasySDK\Kernel\Config;
use app\common\model\User;
use think\App;
use think\facade\Db;
use think\facade\Log;
use app\common\model\Order;
use app\common\model\OrderNotify;
use app\common\helper\EnvHelper;
use think\facade\Request;
/**
* 多端平台支付抽象基类
*/
class AppPlatform extends BasePlatform
{
public function __construct()
{
parent::__construct();
$this->code = 'APP_ANDROID';
$this->env = 'app';
Factory::setOptions($this->getOptions());
}
/**
* 获取系统配置
* @return void
*/
public function get_config(): array
{
// 获取订单编号
$version = Request::param('version', '1.0.0');
$versionNumber = (int) preg_replace('/[^0-9]/', '', $version);
$config = [
'isWebPay' => false,
'buildVersion' => '106',
'version' => '1.0.1',
'userAgreement' => "https://zfunbox.cn?_p=cb20xad0e35094521ae46a1d1fb0ddd1&time=" . time()
];
$is_env_test = EnvHelper::getIsTest();
if ($is_env_test) {
$config['userAgreement'] = "https://testweb.zfunbox.cn?_p=cb20xad0e35094521ae46a1d1fb0ddd1&time=" . time();
}
// $config['userAgreement'] = " https://192.168.1.21:3001?_p=cb20xad0e35094521ae46a1d1fb0ddd1&time=" . time();
$configVersion = (int) preg_replace('/[^0-9]/', '', $config['version']);
if ($versionNumber >= $configVersion) {
$config['buildVersion'] = '105';
// $config['isCheck'] = true;
$config['userAgreement'] = "https://zfunbox.cn/pages/guize/guize?type=4";
}
return $config;
}
/**
* Summary of pay
* @param array $data
* @throws \Exception
* @return array|array{data: array, status: int}
*/
public function pay(array $data): array
{
try {
$data += ['user' => null, 'price' => 0, 'title' => '', 'attach' => 'order_wxs', 'pre' => 'MH_'];
[
'user' => $user,
'price' => $price,
'title' => $title,
'attach' => $attach,
'pre' => $pre,
'quitUrl' => $quitUrl,
'returnUrl' => $returnUrl
] = $data;
if ($user == null) {
//抛出异常
throw new \Exception('用户信息为空');
}
$project_prefix = "AD";
if ($price <= 0) {
//生成订单号订单号为ML_DRAYDMP02025018.... ML_ 前缀固定3位DRA 商户号固定3位YD 项目固定2位MP0 表示微信小程序支付
$order_no = create_order_no_new($pre, "MON", $project_prefix, "APP");
return [
'status' => 1,
'data' => [
'order_no' => $order_no,
'res' => []
]
];
}
$prefix = "ZFA";//$this->GetPrefix();
$config = $this->get_config();
if ($config['isWebPay']) {
$domain = Request::domain();
// Request::param('return_url')
$host = parse_url($domain, PHP_URL_HOST);
$order_no = create_order_no_new($pre, "ZFA", 'H5', "ZFB");
$extend = [
'orderType' => $attach,
];
$extend_str = json_encode($extend, JSON_UNESCAPED_UNICODE);
// 将通知URL和随机字符串保存到order_notify表中
Db::name('order_notify')->insert([
'order_no' => $order_no,
'notify_url' => '',
'nonce_str' => '',
'pay_time' => date('Y-m-d H:i:s'),
'pay_amount' => $price,
'status' => 0,
'retry_count' => 0,
'create_time' => date('Y-m-d H:i:s'),
'update_time' => date('Y-m-d H:i:s'),
'extend' => $extend_str,
'title' => $title,
]);
return [
'status' => 1,
'data' => [
'order_no' => $order_no,
'res' => ['data' => ['order_num' => $order_no], 'requestPay' => $domain . '/api/send_web_pay_order', 'tips' => '']
]
];
}
$title = mb_substr($title, 0, 30);
//生成订单号订单号为ML_DRAYDMP02025018.... ML_ 前缀固定3位DRA 商户号固定3位YD 项目固定2位MP0 表示微信小程序支付
$order_no = create_order_no_new($pre, $prefix, $project_prefix, "ZFB");
$openid = $user['openid'];
$payment_type = 'zfbpay';
$order_type = $attach;
$user_id = $user ? $user['id'] : 0;
// 回调使用的随机数(与支付随机数分离)
$callback_nonce_str = $this->genRandomString();
// 生成新的支付通知URL
$notifyUrl = generatePayNotifyUrl($payment_type, $order_type, $user_id, $order_no, $callback_nonce_str);
$is_env_test = EnvHelper::getIsTest();
if ($is_env_test) {
$is_test = $user['istest'];
if ($is_test == 2) {
$price = 0.01;
}
}
$returnUrl = urldecode($returnUrl);
//2. 发起API调用以支付能力下的统一收单交易创建接口为例
$result = Factory::payment()
->app()
->asyncNotify($notifyUrl)
->pay(
$title, // 支付标题
$order_no, // 商户订单号(唯一)
$price, // 金额
$quitUrl,// 取消地址
$returnUrl// 支付后返回地址
);
//3. 处理响应或异常
if (!empty($result->body)) {
// echo "调用成功" . PHP_EOL;
// 将通知URL和随机字符串保存到order_notify表中
Db::name('order_notify')->insert([
'order_no' => $order_no,
'notify_url' => $notifyUrl,
'nonce_str' => $callback_nonce_str,
'pay_time' => date('Y-m-d H:i:s'),
'pay_amount' => $price,
'status' => 0,
'retry_count' => 0,
'create_time' => date('Y-m-d H:i:s'),
'update_time' => date('Y-m-d H:i:s'),
'title' => $title,
]);
return [
'status' => 1,
'data' => [
'order_no' => $order_no,
'res' => $result->body
]
];
} else {
return ['status' => 0, 'msg' => '支付失败:' . $result];
}
} catch (\Exception $e) {
// echo "调用失败," . $e->getMessage() . PHP_EOL;
// ;
}
return ['status' => 0, 'msg' => '支付失败:'];
}
/**
* 客服发送消息
* @param mixed $user_id
* @param mixed $order_num
* @return array{status: int, data: array, msg: string}
*/
public function sendCustomerServiceMessage($user, $order_num): array
{
// 获取订单编号
$return_url = Request::param('return_url', '');
$message = "用户ID{$user['id']},订单号:{$order_num}";
$order_title = '';
$order_price = 0;
if ($user['openid'] == null) {
return ['status' => 0, 'msg' => '用户openid为空'];
}
$orderNotify = OrderNotify::where([
'order_no' => $order_num,
])->find();
$extend = [];
if ($orderNotify) {
if ($orderNotify['extend'] != '') {
$extend = json_decode($orderNotify['extend'], true);
}
$order_title = $orderNotify['title'];
$order_price = $orderNotify['pay_amount'];
}
if ($order_title == "") {
return ['status' => 0, 'msg' => '订单号错误'];
}
// $this->appid
$web_domain = EnvHelper::getWebDomain();
$extend['returnUrl'] = $return_url;
$extend['openId'] = $user['openid'];
$extend['userId'] = $user['id'];
$extend_str = json_encode($extend, JSON_UNESCAPED_UNICODE);
OrderNotify::where('order_no', $order_num)->update(['extend' => $extend_str]);
return ['status' => 1, 'data' => $web_domain . '/pages/other/web-pay-order?order_num=' . $order_num];
}
/**
* 发货
* @param mixed $openid
* @param mixed $access_token
* @param mixed $order_num
* @param mixed $title
* @return int
*/
public function post_order($user, $order_num): int
{
return 1;
}
public function verify($order_no, $data): bool
{
$result = Factory::payment()->common()->verifyNotify($data);
if ($result) {
return true;
}
return false;
}
/**
* 生成URL链接
* @param int $userId 用户ID
* @return array
*/
public function generateUrlLink($userId): array
{
return ['status' => 1, 'data' => ""];
}
/**
* 获取手机号
* @param string $code 手机号获取凭证
* @return array
*/
public function getMobile($code = ''): array
{
return ['status' => 1, 'data' => ""];
}
/**
* 获取openid
* @param string $code 登录凭证
* @return array
*/
public function getOpenid($code): array
{
return ['status' => 1, 'data' => ""];
}
public function getOptions()
{
$options = new Config();
$options->protocol = 'https';
$options->gatewayHost = 'openapi.alipay.com';
$options->signType = 'RSA2';
$options->appId = '2021005164620165';
// 为避免私钥随源码泄露,推荐从文件中读取私钥字符串而不是写入源码中
$options->merchantPrivateKey = 'MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCktwsJYjHNq3q+oJE7U4vnbt3N+DmRigStdSbNXJfkoxISZvwCVbGUZUkERnfQyg59xKTrywogUvW48i2DibuyAkdtZ0jM/kJN0D0u0WsGCZ1afr8EOIJ1tyCrAS79wV2MUGnQ1BLS3e12SAhNme6hgGFqV1WCyHXvsV+i4i3UTBD3Ai7gBv+UmWQ1R4S4oAWNMjIAw+SxYLIkzG7HFq8vGG2wVnL5/vjsy+cydmBhMOZT1ZccLNR2l+SVr9iNN4UPgXuzrHBdLuDAd0MSzSG1q8xClTLeb/MIuHWrj6rbtkAagCKUM+KP3KcKIdAqHfL0LQb3EQ7b3mG4coF8mrrXAgMBAAECggEAXa0cQcHuwSF9NVzsO+lP79dFnhZF51evQVcXMkQuvoFfjce0Gz/RNqxD0oKhMcU4aJ6ljNR0dd24ke5ppB14+cwCA15yMOOJoeeEZFQFofFl5EmhKS1aRMhZc+fAaeDG6z3wcCusaPB+VH6y+i9JX+A7htcUcsS/Dgq6cVBg8BNG5HcREqJFtSQDbIzimndnRpIY3Jq7WxxOjxNzB7WaSxb60XcV5JwOK+YXhTxewXnOBBq0ByDKHKaPAQrC0cHH6B/P39hgZCROoJDXGvRxk14zbxToXlStwxOfFG8Onljq4y11yCRlinQ9+pDwxA7DdG2wS282elKVs8tYC/BpwQKBgQDryCk/p7P0N+Jx0ioeMuhs1br2UqhMjqtWhKoRboO6g8pR5vL8WN+wKQBJYnaaATq63tmk7lUrTbXLH826psgRW4nqpYme/XBjqt6PcBP6LUt54tOBBsYxfjobN0zko7MZ18MlUVGd5UgbuSgKyFncrPjP1BPXPh4hba0Jc/Y4ZQKBgQCy1tXt47zCx9mrcjknnKvhex/Cv/DmgWKYe+j8LWGLVIjOhw3OBnye7DUXjZiOZfJv028PV/Q5lD7ve8Ah/XtPJl6X0OxA4t8NrCfzraInwPk/p9hkShV600oVYoaO9aOWYVdwnMNLNoThl4kbHtffFsmVv5e3W8B4g7CP/unsiwKBgQCwL6YDFwH1oDzp6K3oWworKZrHrgRtEL8fq4qZ9AcjPI/Wm8k+n/qm3DyGmbkeY4TLVvMzt5SVA0CxRFaq/y3JKqnoWUJ5N9Df6TLd5FZJP8eCkOiTJci7+yLYa35d66VNzljYbeebIVW8waMWS5g6ulZClqss0BIb0KTYx3pZsQKBgHpDLVXJD88J2eG/4RsXnNo11mzJ0+OCKOmeLJXaYIlkbXLkGafz/1aWnWVQxC71u1x/67lNpAWJN815iMy0Ao0F6j1X82wYre0m+Nk6p1UONFg0Y1eM3kpuEIO2K8+oVwID4kd2pHzS9N1VP8Juv54gcggSR6Ju85JwVVDcMQgpAoGBAIqXHdLgAqBwe4Q/wT94DVL93mQ1JQKCF2SEN/AxduA08aBXje/m4ZOGbWf4aTqSQN5LWPR6udzR5zCY7YtT2/eZbIrMxzrEG3M4gztIV11+QttxC1yB040hLyaKcnuqNEWKyPlUOz32TYNbXVY9xKY5esp6wlSTPhd7ys4LgGzv';
// $options->alipayCertPath = '<-- 请填写您的支付宝公钥证书文件路径,例如:/foo/alipayCertPublicKey_RSA2.crt -->';
// $options->alipayRootCertPath = '<-- 请填写您的支付宝根证书文件路径,例如:/foo/alipayRootCert.crt" -->';
// $options->merchantCertPath = '<-- 请填写您的应用公钥证书文件路径,例如:/foo/appCertPublicKey_2019051064521003.crt -->';
//注:如果采用非证书模式,则无需赋值上面的三个证书路径,改为赋值如下的支付宝公钥字符串即可
$options->alipayPublicKey = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl09lU/ezb0ZaNgmlOVp01ZruPdolQgTcV9a42vUv3tYImBGWMGuGF555YGV5yHLVUmHaF0fh6AYWhxOe9iZTlp20vKctkmSVBpjE1UJXlLgn/5L0nzy08+wFCvJ0v3D8/ZwJ4nryjx6rfKbzs+/Ub5X2XuMJj4IhficN/T9tJAWmn8tfccWVw+DGgouIbcCftuGvbOZOAmqzGHU0ZYZXNjCqKithZjO9/9exbA0/5NkETFZqJEDVi09WZ7OS8B0twAPqEnnmYCGb0t8Tn+g1qoWaA/uU3ysQrrQk+q2Xl/PwOT07pCkAgFg4akUQ/poWA9yx2kDnq+3NJxiE0PoIrQIDAQAB';
//可设置异步通知接收服务地址(可选)
//如果需要使用文件上传接口,请不要设置该参数
$options->notifyUrl = "";
//可设置AES密钥调用AES加解密相关接口时需要可选
// $options->encryptKey = "<-- 请填写您的AES密钥例如aa4BtZ4tspm2wnXLb1ThQA== -->";
return $options;
}
}