iPay88 支付网关Gateway-User Scan(用户扫码模式 - PHP实现)

背景

  • 近期因为合作客户有马来西亚的业务,需要对接 【iPay88 支付】
    通过阅读官方文档,发现一头雾水
    相对之前接触的支付文档,个人觉得 iPay88 是最凌乱的
    注意,注册平台账号后,会邮件发送几个开发文档附件(有的跟官网对不上)

    对于开发沟通,还得需要公司业务发送邮件,等个一天多才收到回复,对开发来说,效率很低
    一番折腾,最后梳理一下我的实现步骤,希望能帮到有同样需要的小伙伴

  • 场景要求

满足 在 安卓售卖机 的商品购买页面,下单后,选取iPay88支付方式,弹出 支付二维码 , 引导用户扫码支付

  • 简单介绍
iPay88 是马来西亚领先的在线支付网关提供商,提供本地和国际支付选项。
iPay88 是寻求可靠且功能丰富的支付网关的企业的绝佳选择。

  • 官方文档

【API - iPay88 Technical Spec V1.0.1.pdf】

根据对使用场景的确认,我要参考的便是邮箱提供的附件: iPay88 - Merchant Hosted Payment Gateway e-Wallet (Web Service) - v2.4.1.pdf


☛ 开发步骤

通过阅读开发文档(英文不好,可以是有百度翻译),一步步进行测试

①. 前期准备

  • 首先,需要得到 Merchant CodeMerchant Key,其次需要在后台配置 IP 白名单
  • 其次,根据文档提示,整理开发步骤【User Scan】如下:
Step 1. Merchant sends XML request containing payment details to iPay88 Merchant Hosted Payment 
Gateway Web Service.
Step 2. IPay88 Merchant Hosted Payment Gateway Web Service will verify all the parameters received. 
Step 3. E-Wallet QR code will be generated based on the information received from merchant. 
Step 4. iPay88 Merchant Hosted Payment Gateway Web Service respond back the e-Wallet QR code to 
merchant with a signature through 【XML format】. 
Step 5. The merchant needs to compare the signature from iPay88. Refer to (3.2). 
Step 6. Merchant has to display the e-Wallet’s QR code received in their website. 
Step 7. Trigger payment inquiry requery to iPay88 system to get payment status.
  • 通过梳理测试,我发现仅靠网站和开发文档并不能实现 业务场景所需要的网关支付
    无果,需要向 ipay88官方进行邮件转达,等了一周才得到技术提供的请求示例
    最终得到了 XML/SOAP 请求示例、确认了 SOAPAction,才得以进行下去 …

此处重点吐槽:开发文档不够全面,需及时沟通对方技术团队,才能得到正确的方法(无语…)

②. 确认请求 Header

通过沟通,确认了请求方式为 POST、请求体为 XML/SOAP,以及 Header 信息

  • 重点注意元素:Content-TypeSOAPAction
Reqeust data:

POST https://payment.ipay88.com.my/ePayment/WebService/MHGatewayService/GatewayService.svc HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: text/xml;charset=UTF-8
SOAPAction: "https://www.mobile88.com/IGatewayService/EntryPageFunctionality"
Content-Length: 1125
Host: payment.ipay88.com.my
Connection: Keep-Alive

③. 核心代码提供

根据业务场景,整理核心代码如下

    1. 网关支付、下单方法封装如下:
/**
     * @Notes:iPay88 网关支付,下单业务处理
     * @param string $orderSn 订单编号
     * @param int $orderTotal 订单金额,例如 1.00
     * @return array
     * @throws GuzzleException
     * @User: zhanghj
     * @DateTime: 2023-12-25 15:32
     */
    public function createIPay88GatewayWebOrder($orderSn = '', $orderTotal = 0){
        $err_msg = '';
        $needSignParams = [
            'MerchantKey'   => PayMzConfig::IPAY88_MERCHANT_KEY,	//由iPay88提供,注意保密
            'MerchantCode'  => PayMzConfig::IPAY88_MERCHANT_ID,		//由iPay88提供,注意保密
            'RefNo'         => $orderSn,
            'Amount'        => $orderTotal,
            'Currency'      =>  PayMzConfig::IPAY88_CURRENCY		//默认MYR (马来西亚林吉特)
        ];
        $SignatureNeedStr = $this->dealGetNeedSignatureStr($needSignParams);
        $SignatureStr = $this->iPay88_Sha256_sign($SignatureNeedStr);
        $payment_request_params = [
            'Amount'        => number_format($orderTotal,2),	//注意金额参数形式,Payment amount with two decimals and thousand symbols. Example: 1,278.99
            'BackendURL'    => PayMzConfig::IPAY88_ORDER_PAID_NOTIFY,	//支付成功回调地址
            'Currency'      => PayMzConfig::IPAY88_CURRENCY,
            'MerchantCode'  => PayMzConfig::IPAY88_MERCHANT_ID,
            'PaymentId'     => 233, //支付宝

            'ProdDesc'      => 'IPAY88-FitTech',
            'RefNo'         => $orderSn,
            'Signature'     => $SignatureStr,
            'SignatureType' => 'SHA256',
            'UserContact'   => '0123456789',
            'UserEmail'     => '930959695@qq.com',
            'UserName'      => 'moTzxx',
            'Lang'          => 'UTF-8',
        ];

        $xmlData = $this->dealArrayToSoapXmlForUserScan($payment_request_params);
        
        $options = [
            'body' => $xmlData,
            'headers' => [
                "Accept-Encoding" => "gzip,deflate",
                "Content-Type" => 'text/xml;charset=UTF-8',
                "SOAPAction"   => PayMzConfig::IPAY88_SOAP_ACTION, //不添加会500,需确认值
            ],
        ];

        try {
            $post_url = PayMzConfig::IPAY88_ORDER_METHOD;
            $httpClient = new Client([
                'base_uri' => PayMzConfig::IPAY88_HOST,
                'verify' => false,
                'http_errors' => false
            ]);
            $response  = $httpClient->request('POST',$post_url,$options);
            $res_content = $response->getBody()->getContents();

            //var_dump($res_content);  //用于查看 响应信息
            //字符串替换,方便解析提取
            $res_content = str_replace("a:", "", $res_content);
            $xmlObj  = simplexml_load_string($res_content,'SimpleXMLElement'); // Convert response into object for easier parsing
            $xmlObj->registerXPathNamespace('soap', 'http://schemas.xmlsoap.org/soap/envelope/');
            $xmlResult = $xmlObj->xpath("soap:Body");
            //元素提取
            $objResult = $xmlResult[0]->EntryPageFunctionalityResponse->EntryPageFunctionalityResult;
            $ipay88_qrcode = $objResult->QRCode->__toString()??'';
            $payRes['_qr'] = $ipay88_qrcode;
        }catch (BadResponseException  $exception){
            $err_msg = $exception->getResponse()->getBody()->getContents();
        }catch (\Exception $exception){
            $err_msg = $exception->getMessage();
        }
        return [$err_msg,$payRes??[]];
    }
    1. 提供 加密、xml/soap 构造方法
    /**
     * @Notes:构造请求 xml/soap
     * @param $arr
     * @return string
     * @User: zhanghj
     * @DateTime: 2024-01-05 10:54
     */
    public function dealArrayToSoapXmlForUserScan($arr) {
        $xml = '<?xml version="1.0" encoding="UTF-8"?>';
        $xml.= '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:mob="https://www.mobile88.com" xmlns:mhp="http://schemas.datacontract.org/2004/07/MHPHGatewayService.Model">';
        $xml.= '<soapenv:Header/>';
        $xml.= '<soapenv:Body>';
        $xml.= '<mob:EntryPageFunctionality>';
        $xml.= '<mob:requestModelObj> ';
        foreach ($arr as $key => $val) {
            $xml .= "<mhp:" . $key . ">" . $val . "</mhp:" . $key . ">";
        }
        $xml .= '</mob:requestModelObj>';
        $xml .= '</mob:EntryPageFunctionality>';
        $xml .= '</soapenv:Body>';
        $xml .= '</soapenv:Envelope>';
        return $xml;
    }

    /**
     * @Notes:构造待加密串
     * @param array $needSignParams	待加密字符串
     * @return string
     * @User: zhanghj
     * @DateTime: 2024-01-05 10:55
     */
    public function dealGetNeedSignatureStr($needSignParams = []){
        $need_sign_str = '';
        if ($needSignParams && is_array($needSignParams)){
            $MerchantKey = $needSignParams['MerchantKey']??'';
            $MerchantCode = $needSignParams['MerchantCode']??'';
            $RefNo = $needSignParams['RefNo']??'';
            $CCTransId  = $needSignParams['CCTransId']??'';
            $Amount = $needSignParams['Amount']??'';
            $Amount = bcmul($Amount,100,0);
            $Currency = $needSignParams['Currency']??'';
            $BarcodeNo = $needSignParams['BarcodeNo']??'';
            $need_sign_str = $MerchantKey.$MerchantCode.$RefNo.$CCTransId.$Amount.$Currency.$BarcodeNo;
        }
        return $need_sign_str ??'';
    }

    /**
     * @Notes:sha256 加密
     * @param string $concatenated_string
     * @return string
     * @User: zhanghj
     * @DateTime: 2024-01-05 10:55
     */
    public function iPay88_Sha256_sign($concatenated_string = ''){
        return  hash('sha256', $concatenated_string);
    }

④. 接口请求测试

根据以上代码的部署,已经配置信息的整合,进行正式请求测试

    1. 构造的 XML/SOAP 请求体如下 (测试代码生成的,可作为参考排查错误)
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:mob="https://www.mobile88.com"
    xmlns:mhp="http://schemas.datacontract.org/2004/07/MHPHGatewayService.Model">
    <soapenv:Header />
    <soapenv:Body>
        <mob:EntryPageFunctionality>
            <mob:requestModelObj>
                <mhp:Amount>1.00</mhp:Amount>
                <mhp:BackendURL>http://clientapi.xxx.xxx.com/notify/ipay88_order_notify</mhp:BackendURL>
                <mhp:Currency>MYR</mhp:Currency>
                <mhp:MerchantCode>MXXXXX</mhp:MerchantCode>
                <mhp:PaymentId>233</mhp:PaymentId>
                <mhp:ProdDesc>IPAY88-FitTech</mhp:ProdDesc>
                <mhp:RefNo>TM20240105007</mhp:RefNo>
                <mhp:Signature>c8699b731403c56567229150829d8c5f15865092b358b56e855136bd20a56b63</mhp:Signature>
                <mhp:SignatureType>SHA256</mhp:SignatureType>
                <mhp:UserContact>0123456789</mhp:UserContact>
                <mhp:UserEmail>930959695@qq.com</mhp:UserEmail>
                <mhp:UserName>moTzxx</mhp:UserName>
                <mhp:Lang>UTF-8</mhp:Lang>
            </mob:requestModelObj>
        </mob:EntryPageFunctionality>
    </soapenv:Body>
</soapenv:Envelope>
    1. 下单接口,请求成功后,返回信息如下(可根据SOAP摘取需要的信息)
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    <s:Header>
        <ActivityId CorrelationId="f9f82a65-4640-4f96-ad26-180fce5aa558"
            xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">00000000-0000-0000-0000-000000000000
        </ActivityId>
    </s:Header>
    <s:Body>
        <EntryPageFunctionalityResponse xmlns="https://www.mobile88.com">
            <EntryPageFunctionalityResult xmlns:a="http://schemas.datacontract.org/2004/07/MHPHGatewayService.Model"
                xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
                <a:ActionType i:nil="true" />
                <a:Amount>1.00</a:Amount>
                <a:AmountBeforeDiscount>1.00</a:AmountBeforeDiscount>
                <a:AuthCode i:nil="true" />
                <a:BankMID i:nil="true" />
                <a:BindCardErrDescc i:nil="true" />
                <a:CCName i:nil="true" />
                <a:CCNo i:nil="true" />
                <a:CardType i:nil="true" />
                <a:Currency>MYR</a:Currency>
                <a:DCCConversionRate i:nil="true" />
                <a:DCCStatus>0</a:DCCStatus>
                <a:Discount>0.00</a:Discount>
                <a:ErrDesc i:nil="true" />
                <a:Lang i:nil="true" />
                <a:MerchantCode>MXXXXX</a:MerchantCode>
                <a:OriginalAmount i:nil="true" />
                <a:OriginalCurrency i:nil="true" />
                <a:PaymentId>233</a:PaymentId>
                <a:PaymentType i:nil="true" />
                <a:QRCode>
                    https://payment.ipay88.com.my/ePayment/WebService/QR/AliPayOfflineQR/QrAli1704423760.33316-T042898260024.Png
                </a:QRCode>
                <a:QRValue>https://qr.alipay.com/bax023952ksmljfh8r3q00ec</a:QRValue>
                <a:RefNo>TM20240105007</a:RefNo>
                <a:Remark i:nil="true" />
                <a:Requery i:nil="true" />
                <a:S_bankname i:nil="true" />
                <a:S_country i:nil="true" />
                <a:SettlementAmount i:nil="true" />
                <a:SettlementCurrency i:nil="true" />
                <a:Signature>6c9cee7f86ed3f1115cb1b899e8990ebb43e1ac692c1e97d475e94bf2cd43d48</a:Signature>
                <a:Status>1</a:Status>
                <a:TokenId i:nil="true" />
                <a:TransId>T042898260024</a:TransId>
                <a:Xfield1 i:nil="true" />
                <a:Xfield2 i:nil="true" />
            </EntryPageFunctionalityResult>
        </EntryPageFunctionalityResponse>
    </s:Body>
</s:Envelope>
    1. 请求测试代码如下:
$pay_order_sn = $request->get('order_sn','');
list($err_msg,$iPay88Result) = (new PayMzService())->createIPay88GatewayWebOrder($pay_order_sn,1.00);
var_dump($err_msg);
var_dump($iPay88Result);
var_dump('iPay88 支付开发中...');
    1. 返回代码显示:
string(0) ""
array(1) {
["_qr"]=>
string(108)
"https://payment.ipay88.com.my/ePayment/WebService/QR/AliPayOfflineQR/QrAli1704425934.76971-T042904908324.Png"
}
string(25) "iPay88 支付开发中..."
    1. 支付二维码显示、支付宝扫码结果如下:

⑤. 支付回调处理

回调处理接口,即下单请求时配置的参数 BackendURL

    /**
     * @Notes:iPay88 马来西亚 订单支付回调接口
     * @User: zhanghj
     * http://clientapi.xxx.xxx.com/notify/ipay88_order_notify
     * @DateTime: 2023-12-26 16:17
     */
    public function actionIpay88OrderNotify()
    {
        $arr_res = $_REQUEST;
        $merchantcode = $arr_res["MerchantCode"]??'';
        $paymentid = $arr_res["PaymentId"]??'';
        $out_trade_no = $arr_res["RefNo"]??'';
        $pay_total_fee = $arr_res["Amount"]??'';
        $ecurrency = $arr_res["Currency"]??'';
        $remark = $arr_res["Remark"]??'';
        $transid = $arr_res["TransId"]??'';
        $authcode = $arr_res["AuthCode"]??'';
        $estatus = $arr_res["Status"]??'';
        $errdesc = $arr_res["ErrDesc"]??'';
        $signature = $arr_res["Signature"]??'';

        $arr_record_pay = [
            'Status' => $estatus,
            'Amount' => $pay_total_fee,
            'Currency' => $ecurrency,
            'TransId' => $transid,
            'ErrDesc' => $errdesc
        ];
        $payment_json_str = json_encode($arr_record_pay,JSON_UNESCAPED_UNICODE);
        $this->recordLocalFileLog('ipay88',"notify data :".json_encode( $arr_res) );
        $this->recordLocalFileLog('ipay88',"notify data :".$payment_json_str );

        if ($estatus==1) {
            // update order to PAID
           
            echo "RECEIVEOK";
        } else{
            // update order to FAIL
            
        }
    }


    /**
     * @Notes:记录本地文件 日志信息
     * @param string $op_type
     * @param string $log_content
     * @return bool
     * @User: zhanghj
     * @DateTime: 2023-12-22 13:59
     */
    public static function recordLocalFileLog($op_type = '',$log_content = '') {
        $time_stamp = date("Y-m-d H:i:s", time());
        $log_file_name = 'ipay88';
        $file = dirname(Yii::$app->basePath)."/api/log/{$log_file_name}_".date("Ymd").".txt";
        $handle = fopen( $file, 'a+');
        fwrite( $handle , "[{$time_stamp}]: ".$log_content."\n");
        fclose( $handle );
    }

附录

①. 参考文章

    1. php 对接国外支付 ipay88支付
    1. 分布式.RPC-WebService三要素,三个规范, Soap协议
    1. 如何修复guzzlehttp截断的500内部服务器错误代码点火器

②. 问题整理

    1. 支付金额
      测试发现,金额小于 1.00 无法生成支付二维码
    1. 回调处理
      注意文档中提到的一点,需要在后台配置地址
    1. 请求测试
      个人经验:代码测试一般找问题较慢,推荐先使用 Post请求工具,提前测试
      如下是我用 APIPost 工具测试截图
    1. Payment ID 取值参考

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/294226.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

TikTok革新游戏规则:解读短视频对社交媒体的影响

在社交媒体的巨浪中&#xff0c;TikTok以其独特的短视频形式和强大的创意社区&#xff0c;重新定义了游戏规则。这个以15秒视频为核心的平台&#xff0c;不仅让用户获得了表达自我的新方式&#xff0c;更深刻地影响了社交媒体的演进。本文将深入解读TikTok对社交媒体的影响&…

OpenSSL——升级

OpenSSL&#xff08;Open Secure Sockets Layer&#xff09;是一个开源的软件库&#xff0c;提供了SSL和TLS协议的实现&#xff0c;用于加密通信。它广泛用于安全连接&#xff0c;例如在网站上通过HTTPS协议进行安全的数据传输. 但是从openssl申请道德证书是不安全的。对于网站…

打破闲鱼商品搜索瓶颈!云端电商API接口让你畅享商品详情关键词搜索的便利!

在闲鱼卖家的日常经营中&#xff0c;商品搜索是一个至关重要的环节。但是&#xff0c;由于闲鱼平台商品信息繁杂&#xff0c;卖家往往很难通过手动搜索的方式找到符合自己需求的商品。为了解决这一问题&#xff0c;云端电商API接口应运而生。联讯数据将详细介绍云端电商API接口…

第一届能源电子产业创新大赛太阳能光伏赛道决赛及颁奖仪式在宜宾成功举办

在工业和信息化部电子信息司指导下&#xff0c;由工业和信息化部产业发展促进中心和宜宾市人民政府主办&#xff0c;宜宾市经济和信息化局、宜宾高新技术产业园区管理委员会承办的第一届能源电子产业创新大赛太阳能光伏赛道决赛及颁奖仪式于2024年1月3日-5日在宜宾市成功举办。…

亲授秘籍!独立站推广神级攻略,不信你试试?

在电商市场竞争激烈的今天&#xff0c;对于跨境电商卖家而言&#xff0c;有效推广独立站已经成为了一项关键任务。为了提升品牌知名度和吸引更多的潜在客户&#xff0c;我们需要不断探索新的推广方式和策略。在本文中&#xff0c;龙哥将分享一些成功的推广经验&#xff0c;以下…

java 6种深拷贝集合方式及其性能差异对比

文章目录 ArrayList 构造方法拷贝运行1000次耗时 1ms for循环拷贝运行1000次耗时 14ms Stream流 collect实现拷贝运行1000次耗时 54ms Stream流spring的BeanUtils实现拷贝运行1000次耗时 2468 ms Hutool工具实现拷贝Hutool 5.7.13版本运行1000次耗时 64674 msHutool 5.8.24版本…

芯片金线包封胶的使用注意事项是什么?

芯片金线包封胶的使用注意事项是什么?金线包封胶是一种高性能、高粘度的密封胶&#xff0c;广泛应用于电子、电器、汽车等领域。它具有良好的防水、防潮、防震等性能&#xff0c;能够保护产品内部零件不受环境影响&#xff0c;提高产品的使用寿命。然而&#xff0c;在使用金线…

记一次RabbitMQ服务器异常断电之后,服务重启异常的处理过程

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 问题描述&#xff1a; 机房突然停电&#xff0c;rabbitmq的主机异常断电&#xff0c;集群服务全部需要重启。但是在执行service…

热泵,预计到2025年市场规模将达到650亿美元

热泵是一种利用空气、水、地热等低品位能源&#xff0c;转化为高品位热能&#xff0c;提供供暖、热水和冷却等服务的热力设备。近年来&#xff0c;热泵市场逐步发展壮大&#xff0c;成为新能源市场的重点发展领域。全球市场分析&#xff1a; 近年来&#xff0c;全球绿色环保理念…

QT上位机开发(动态库dll的开发)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 有的时候&#xff0c;我们不想把所有的代码都放在一个exe里面&#xff0c;这个时候我们就需要引入dll动态库的概念。在windows平台上面&#xff0c…

接口测试测什么?一个简单问题把我难住了!

那么设计测试用例时我们主要考虑如下几个方面&#xff1a; 01、功能测试 接口的功能是否正确实现了 接口是否按照设计文档中来实现 &#xff08;比如username参数写为了user&#xff0c;那么这就不符合&#xff0c;因为接口文档在整个开发中都需要使用&#xff0c;所以接口实…

Spss Amos 28安装包下载及安装教程

Amos 28下载链接&#xff1a;https://docs.qq.com/doc/DUnhwUXFnTGtyRnJ1 1.鼠标右键解压到“Amos 28” 2.选中Setup&#xff0c;鼠标右击选择“以管理员身份运行” 、3.点击“Next” 4.选择I accept the terms in the license agreement&#xff0c;点击“Next” 5.选择软件安…

Centos7.9或Deebian12安装K3s和k9s详细流程

1、在线安装k3s 安装的版本为&#xff1a;v1.23.15k3s1 curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRRORcn INSTALL_K3S_VERSION"v1.23.15k3s1" sh - 2、安装完成&#xff0c;测试 kubectl get nodes正常输出即没…

【教学类-综合练习-02】20231208 大3班 数字加减法练习(数字火车、X—Y加法减法、X乘法、X—Y数字分合)

教学情况 时间&#xff1a;20231208 班级&#xff1a;大3班 人数&#xff1a;21 目的&#xff1a;幼儿根据自己的能力水平&#xff0c;选择适合的数学题&#xff08;多款样式&#xff09; 在昨天大4班制作的基础上&#xff0c;特地打印一些小纸片数学题&#xff08;节省纸…

WPF DatePicker与Calendar的使用和样式修改

什么是DatePicker&#xff0c;Calendar Calendar&#xff1a;日历&#xff08;显示年月日视图控件&#xff09;DatePicker&#xff1a;日期选择器&#xff08;是一个更小的控件&#xff0c;点击控件时才会弹出一个日历&#xff09; Calendar使用 常用属性 DisplayMode&#…

【漏洞复现】通天星CMSV6车载监控平台FTP匿名访问

Nx01 产品简介 深圳市通天星科技有限公司&#xff0c;是一家以从事计算机、通信和其他电子设备制造业为主的企业。通天星车载视频监控平台软件拥有多种语言版本。应用于公交车车载视频监控、校车车载视频监控、大巴车车载视频监控、物流车载监控、油品运输车载监控、警车车载视…

基于Java SSM框架实现宠物管理系统项目【项目源码+论文说明】

基于java的SSM框架实现宠物管理系统演示 摘要 随着我国经济的快速发展&#xff0c;人民生活水平的不断提高&#xff0c;宠物逐渐成为许多宠物爱好者的一种生活方式。 宠物的品种也越来越多样化&#xff0c;宠物不仅能给生活带来乐趣还可以成为空巢老人&#xff0c;独生子女很…

windows安装kafka以及kafka管理工具推荐

windows安装 1.下载地址 下载地址 下载最新版本的.tgz文件解压 2.修改配置 修改config目录下的zookeeper.properties中的dataDir属性 server.properties文件中的log.dir属性 3.启动zookeeper 进入到bin\windows\下的用cmd输入zookeeper-server-start.bat ..\..\config\zo…

ShardingSphere-JDBC初探

引言 为什么使用分库分表&#xff1f; 数据量太大单表放不下&#xff0c;并且公司不希望切换产品&#xff0c;可选的方案不多&#xff0c;ShardingSphere就是不错的选择。 切换产品指的是换成es、clickhouse、hbase这种支持大数据&#xff0c;试想一下切换产品对整个项目的改…

ChatGPT 进行 SEO的使用技巧

搜索引擎优化 (SEO) 是使网站对搜索引擎友好的一种不断发展的实践。 自搜索引擎和新兴技术的发展以来&#xff0c;它从未保持不变。 最近发布的 ChatGPT 是一种人工智能对话工具&#xff0c;似乎在搜索引擎优化方面有很好的应用。 从创建吸引人的标题到只需一个简短的提示就可…