首页
美图
服务
付费
树洞
云主机
推荐
邻居
支付
开发
书单
更多
我的足迹
罗盘时钟
圈小猫
工作打分
给我留言
本站统计
推荐
M商城
欣悦云店
txt阅读器
VPS监控
证书监控
网址导航
在线工具
Search
1
docker和docker-compose一键安装脚本
4,654 阅读
2
采用Prometheus+Grafana 监控H3C交换机状态
4,036 阅读
3
WooCommerce对接第三方支付插件开发
3,799 阅读
4
grafana的Dashboard面板添加阈值报警
2,673 阅读
5
自己有一台云主机可以做什么
2,602 阅读
虚拟化
数据库
运维
基础知识
监控预警
数据展示
运维工具
web安全
系统服务
开发
python
php
java
shell
go
项目
博客
电商
工具
娱乐
综合
VPS相关
规范文档
知识总结
经验分享
读书笔记
关于
Search
标签搜索
django
python
运维工具
支付对接
电商平台
Joe主题
docker
wordpress
woocommerce
支付通道
zabbix
蓝鲸智云
运维
grafana
监控
运维知识
typecho
php
mysql
nginx
行云流水
累计撰写
321
篇文章
累计收到
348
条评论
首页
栏目
虚拟化
数据库
运维
基础知识
监控预警
数据展示
运维工具
web安全
系统服务
开发
python
php
java
shell
go
项目
博客
电商
工具
娱乐
综合
VPS相关
规范文档
知识总结
经验分享
读书笔记
关于
页面
美图
服务
树洞
云主机
邻居
支付
书单
给我留言
本站统计
推荐
M商城
txt阅读器
网址导航
搜索到
83
篇与
的结果
2024-09-02
支付网关DaxPay部署测试改造过程
前言DaxPay单商户是一套开源支付网关系统,已经对接支付宝、微信支付相关的接口。可以独立部署,提供接口供业务系统进行调用,不对原有系统产生影响, 适用于小型项目或简单收单的场景。本文记录部署测试记录。{card-default label="收款页面" width="90%"}{/card-default}核心技术栈JDK,1.8+,11版本可以正常使用,但17+版本暂不支持SpingBoot, 2.7xRedis, 5.x版本以上Mysql,5.7.X以上Vue,前端框架3.x项目部署过程数据库mysql,redis的部署过程略过。可以查阅一下往期的文章。本文主要记录项目代码部署的相关过程。所有项目代码的地址: 【支付源码】开源免费支付系统DaxPay源码数据库创建一个daxpay的数据实例。同时在后端项目中_config/sql目录下找到dax-pay.sql数据库脚本文件,导入daxpay数据库。# 建库 mysql -uroot -pmariadb@xxx -h 127.0.0.1 CREATE DATABASE `daxpay` DEFAULT CHARACTER SET utf8 COLLATE utf8_bin; create user 'dpuser'@'%' IDENTIFIED BY 'dpuserxxx'; grant all privileges on daxpay.* to 'dpuser'@'%'; flush privileges; # 导入demo数据 mysql -udpuser -pdpuserxxx -h 127.0.0.1 daxpay < ./_config/mysql/dax-pay.sqljava环境利用java和maven打包后端代码,在打包之前修改application.yml内的数据库连接信息。# java和maven的安装 yum install java-1.8.0-openjdk java-1.8.0-openjdk-devel wget https://downloads.apache.org/maven/maven-3/3.8.8/binaries/apache-maven-3.8.8-bin.tar.gz tar xvf apache-maven-3.8.8-bin.tar.gz mv apache-maven-3.8.8 /usr/local/maven # maven配置国内源 vim ~/.m2/settings.xml 内容见下面... # maven版本验证 java -version mvn -version # 项目打包 mvn -B clean package -Dmaven.test.skip=true -Dmaven.javadoc.skip=true -Dautoconfig.skipmaven国内源:<settings> <mirrors> <!-- 阿里云镜像 --> <mirror> <id>aliyun</id> <mirrorOf>*</mirrorOf> <url>https://maven.aliyun.com/repository/public</url> </mirror> <!-- 华为云镜像 --> <mirror> <id>hwcloud</id> <mirrorOf>*</mirrorOf> <url>https://mirrors.huaweicloud.com/repository/maven/</url> </mirror> <!-- 清华大学镜像 --> <mirror> <id>tsinghua</id> <mirrorOf>*</mirrorOf> <url>https://mirrors.tuna.tsinghua.edu.cn/maven/</url> </mirror> <!-- 中科大镜像 --> <mirror> <id>ustc</id> <mirrorOf>*</mirrorOf> <url>https://mirrors.ustc.edu.cn/maven/</url> </mirror> </mirrors> </settings>项目启动项目代码在docker内运行,使用docker-compose.yml管理。docker和docker-compose的安装见往期文章。构建docker镜像:隐藏内容,请前往内页查看详情构建命令:docker build -t dax-start:latest .docker-compose.yml内容隐藏内容,请前往内页查看详情前端代码因为项目采用前后端分离架构,前端代码需要单独构建。构建后将代码传输到服务器,然后用nginx服务器提供服务。# 安装node和pnpm环境,博主是mac系统: brew install node@16 pnpm@8 # 配置环境变量 echo 'export PATH="/opt/homebrew/opt/node@20/bin:$PATH"' >> ~/.zshrc echo 'export PATH="/opt/homebrew/opt/pnpm@8/bin:$PATH"' >> ~/.zshrc # 配置国内源 pnpm config set registry https://registry.npmmirror.com # 项目构建 pnpm install pnpm buildnginx服务服务有nginx代理静态资源,前端放caddy用于自动申请ssl证书。nginx配置:隐藏内容,请前往内页查看详情caddy2代理配置:隐藏内容,请前往内页查看详情至此所有配置完成。可以通过web登录后台,配置账号,支付通道等。{card-default label="管理后台" width="80%"}{/card-default}
2024年09月02日
14 阅读
0 评论
0 点赞
2024-08-21
新客户端IP一键过白功能开发与配置
前言部署了一个自己使用的web服务,不想对公网开放。最初用iptables对自己当前的电脑IP开放,禁止其他IP访问。每次路由器重启,或者在外出差,IP经常变动。需要登录服务器,新增新的IP。决定改变控制方式,利用nginx的IP白名单功能,同时用flask写了一个对公网开放的页面。当地址变动时,访问此页面。点击一键更新,就把最新的ip加入到nginx的白名单。同时重新加载nginx配置生效。{card-default label="ip更新页面" width="85%"}{/card-default}被控制服务需要进行ip访问控制,不对公网开放的nginx配置信息。default.conf配置用加载了ip白名单文件whitelist.conf# Appadmin server { listen 80; server_name 0.0.0.0; root /www/web/maccms_v10/; server_tokens off; #include none.conf; index index.php index.html index.htm; access_log /www/web_logs/wp_access.log wwwlogs; error_log /www/web_logs/wp_error.log notice; #auth_basic "请输入用户和密码"; # 验证时的提示信息 #auth_basic_user_file /etc/nginx/password; # 认证文件 location /{ include whitelist.conf; #默认位置路径为/etc/nginx/ 下, #如直接写include whitelist.conf,则只需要在/etc/nginx目录下创建whitelist.conf deny all; } location ~ \.php$ { fastcgi_pass php:9000; fastcgi_index index.php; include fcgi.conf; } #需要注意伪静态的配置 if (!-e $request_filename) { rewrite ^/index.php(.*)$ /index.php?s=$1 last; rewrite ^/api.php(.*)$ /api.php?s=$1 last; rewrite ^/adm0.php(.*)$ /adm0.php?s=$1 last; rewrite ^(.*)$ /index.php?s=$1 last; break; } location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 30d; } location ~ .*\.(js|css)?$ { expires 12h; } }whitelist.conf文件内存放需要开放的IP,文件内容:allow 101.31.158.153;控制服务文章开头的一键放通页面用flask框架实现, 单独部署app.py主要实现逻辑,有两个接口。一个接口提供页面,一个接口负责获取IP后更新,同时重新加载被控制服务的nginx配置隐藏内容,请前往内页查看详情index.html提供文章开头的一键更新功能的页面代码<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>IP 过白</title> <link rel="stylesheet" href="styles.css"> <!-- Link to external CSS file --> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <style> body { font-family: Arial, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; background-color: #f0f0f0; margin: 0; } .container { text-align: center; background-color: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); } h1 { color: #333; } #uploadBtn { background-color: #007bff; color: #fff; border: none; padding: 10px 20px; border-radius: 5px; cursor: pointer; font-size: 16px; transition: background-color 0.3s ease; } #uploadBtn:hover { background-color: #0056b3; } #uploadBtn:focus { outline: none; } </style> </head> <body> <div class="container"> <h1>更新此客户端IP</h1> <button id="uploadBtn">确认</button> </div> <script> $(document).ready(function() { $('#uploadBtn').click(function() { $.ajax({ type: 'POST', url: '/upload_ip', success: function(response) { if (response.status === 'success') { alert('IP 更新成功: ' + response.ip); ('Error: ' + response.message); } }, error: function() { alert('发生错误.'); } }); }); }); </script> </body> </html>服务启动控制服务通过systemd加载,配置文件为:/etc/systemd/system/ipallow.service。配置内容为[Unit] Description=IpAllow App [Service] User=root WorkingDirectory=/opt/ipallow ExecStart=/usr/local/bin/gunicorn -w 2 -b 0.0.0.0:801 app:app Restart=always [Install] WantedBy=multi-user.targetcaddy代理控制服务启动了服务器的801端口,通道caddy2代理到443,然后通过公网可访问。不用nginx代理的原因是控制服务会重启nginx,导致前端页面在等待返回结构时异常。b.test.xyz:443 { tls service@test.xyz encode gzip log { output file /logs/access.log } header / { Strict-Transport-Security "max-age=31536000;includeSubdomains;preload" } #访问认证 basicauth / { cms $2a$14$bNLxxxxxxxxxxxxxxxxxxxxxxGAbzyOUyoBn1rjfpN/O } ## HTTP 代理配置 reverse_proxy http://192.168.0.203:801 { header_up X-Real-IP {http.request.remote.host} header_up X-Forwarded-For {http.request.remote.host} header_up X-Forwarded-Port {http.request.port} header_up X-Forwarded-Proto {http.request.scheme} } }caddy认证密码生产caddy的认证密码caddy hash-password --plaintext 'cmsxxxx'
2024年08月21日
25 阅读
0 评论
0 点赞
2024-08-10
为woocommerce开发支付网关插件,对接支付通道
前言WooCommerce模板众多,可以选择出我们需要的模板,生态好,而且数千个钩子更加利于开发者开发。本文分享如何为woocommerce独立站开发第三方支付插件。创建插件因为WooCommerce有很多的钩子,所以我们在开发支付网关的时候,只需按照一个“框架”来开发就好,下面的是插件框架<?php /* * Plugin Name: WooCommerce自定义支付网关 * Plugin URI: https://www.kekc.cn/ * Description: 这个插件是我们开发自定义支付网关时的示例插件 * Author: kekc * Author URI: https://www.kekc.cn * Version: 1.0.0 */ /* * 这个动作钩子将我们的PHP类注册为WooCommerce的支付网关 */ add_filter( 'woocommerce_payment_gateways', 'kekc_cn_add_gateway_class' ); function kekc_cn_add_gateway_class( $gateways ) { $gateways[] = 'WC_kekc_cn_Gateway'; // 类似一个支付别名 return $gateways; } /* * 注意它是在plugins_loaded动作钩子里面的,也就是插件加载时的hook */ add_action( 'plugins_loaded', 'kekc_cn_init_gateway_class' ); function kekc_cn_init_gateway_class() { class WC_kekc_cn_Gateway extends WC_Payment_Gateway { /** * 从这里开始执行,我们先放在这,之后详细讲 */ public function __construct() { ... } /** * 插件选项,也就是插件的设置页面的设置项,也在之后详细说 */ public function init_form_fields(){ ... } /** * 支付字段,填一些表单数据,字段等,比如用信用卡支付的信用卡号之类的 */ public function payment_fields() { ... } /* * 自定义CSS和JS,在大多数情况下,只有当你决定使用自定义支付字段时才需要。 */ public function payment_scripts() { ... } /* * 字段验证 */ public function validate_fields() { ... } /* * 在这里处理付款 */ public function process_payment( $order_id ) { ... } /* * 如果你需要一个webhook,如PayPal IPN等,可以新建个函数,以便在其他函数中使用它 */ public function webhook() { ... } } }具体代码构造函数public function __construct() { $this->id = 'kekc_cn'; // 支付网关插件ID,可以字符串,但是要唯一 $this->icon = ''; // 将显示在结账页上你的支付网关图标。内容为URL $this->has_fields = true; // 你需要自定义支付网关字段就填true $this->method_title = 'kekc_cn Gateway'; $this->method_description = 'Description of kekc_cn payment gateway'; // 显示在选项页上 // 网关可以支持订阅、退款、保存支付方式。 // 但在本教程中,我们从简单的支付开始 $this->supports = array( 'products' ); // 所有选项字段的方法 $this->init_form_fields(); // 加载设置 $this->init_settings(); $this->title = $this->get_option( 'title' ); $this->description = $this->get_option( 'description' ); $this->enabled = $this->get_option( 'enabled' ); $this->testmode = 'yes' === $this->get_option( 'testmode' ); $this->private_key = $this->testmode ? $this->get_option( 'test_private_key' ) : $this->get_option( 'private_key' ); $this->publishable_key = $this->testmode ? $this->get_option( 'test_publishable_key' ) : $this->get_option( 'publishable_key' ); // 这个动作钩子保存上面的设置 add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) ); // 我们需要自定义的JavaScript来获得token add_action( 'wp_enqueue_scripts', array( $this, 'payment_scripts' ) ); // 你也可以在这里注册一个webhook // add_action( 'woocommerce_api_{webhook name}', array( $this, 'webhook' ) ); } 添加管理配置字段这个的话都需要把,比如开发易支付支付网关,就需要url,商户ID,商户token等,还需要"启用/禁用","标题","描述"和"测试模式"等设置项。public function init_form_fields(){ $this->form_fields = array( 'enabled' => array( 'title' => 'Enable/Disable', 'label' => 'Enable kekc_cn Gateway', 'type' => 'checkbox', 'description' => '', 'default' => 'no' ), 'title' => array( 'title' => 'Title', 'type' => 'text', 'description' => 'This controls the title which the user sees during checkout.', 'default' => 'Credit Card', 'desc_tip' => true, ), 'description' => array( 'title' => 'Description', 'type' => 'textarea', 'description' => 'This controls the description which the user sees during checkout.', 'default' => 'Pay with your credit card via our super-cool payment gateway.', ), 'testmode' => array( 'title' => 'Test mode', 'label' => 'Enable Test Mode', 'type' => 'checkbox', 'description' => 'Place the payment gateway in test mode using test API keys.', 'default' => 'yes', 'desc_tip' => true, ), 'test_publishable_key' => array( 'title' => 'Test Publishable Key', 'type' => 'text' ), 'test_private_key' => array( 'title' => 'Test Private Key', 'type' => 'password', ), 'publishable_key' => array( 'title' => 'Live Publishable Key', 'type' => 'text' ), 'private_key' => array( 'title' => 'Live Private Key', 'type' => 'password' ) ); }验证信息为什么要验证信息呢?我们有的支付网关,可以先验证用户信息,比如你银行卡支付需要接收短信验证码之类的,来确认是用户本人操作,那就需要此步骤,反之,如微信支付、支付宝支付、易支付、PayPal等等,支付都在第三方处理,不在我们服务器,所以无需验证,你可以直接空着或者是删除这个验证类方法。{card-describe title="比如信用卡"}客户填写其卡数据并单击“购买”按钮。我们使用WooCommerce中的事件延迟表单提交,并将带有卡数据的AJAX请求直接发送到我们的支付处理器,checkout_place_order如果客户详细信息正常,处理器将返回一个令牌,我们将其添加到下面的表格中,现在我们可以提交表格(当然在JS中),我们使用PHP中的令牌通过支付处理器的API捕获付款。{/card-describe}PHP代码部分public function payment_scripts() { // 我们只需要在购物车/结账页面用JavaScript来处理一个token,看它是否正确? if ( ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) ) { return; } // 如果我们的支付网关被禁用,我们就不需要js了 if ( 'no' === $this->enabled ) { return; } // 如果没有设置API密钥,就不需要js if ( empty( $this->private_key ) || empty( $this->publishable_key ) ) { return; } // 除非你的网站处于测试模式,否则不要在没有SSL的情况下验证。 if ( ! $this->testmode && ! is_ssl() ) { return; } // 让我们假设这是我们的支付处理器的JavaScript,它能得到一个token wp_enqueue_script( 'kekc_cn_js', 'https://www.kekc_cnpayments.com/api/token.js' ); // 这是在插件目录中的自定义JS,与token.js一起处理。 wp_register_script( 'woocommerce_kekc_cn', plugins_url( 'kekc_cn.js', __FILE__ ), array( 'jquery', 'kekc_cn_js' ) ); // 在大多数支付处理程序中,必须使用公共密钥来获得一个token wp_localize_script( 'woocommerce_kekc_cn', 'kekc_cn_params', array( 'publishableKey' => $this->publishable_key ) ); wp_enqueue_script( 'woocommerce_kekc_cn' ); }JS代码部分var successCallback = function(data) { var checkout_form = $( 'form.woocommerce-checkout' ); // 添加一个隐藏的token提交框 // console.log(data)查看token checkout_form.find('#kekc_cn_token').val(data.token); // 禁止token Request checkout_form.off( 'checkout_place_order', tokenRequest ); // 现在提交form表单 checkout_form.submit(); }; var errorCallback = function(data) { console.log(data); }; var tokenRequest = function() { // 这里将是一个支付网关函数,处理来自你的表单的所有卡片数据,也许它需要你的可发布API密钥,即kekc_cn_params.publishableKey, // 并在成功时触发successCallback(),失败时触发errorCallback。 return false; }; jQuery(function($){ var checkout_form = $( 'form.woocommerce-checkout' ); checkout_form.on( 'checkout_place_order', tokenRequest ); });添加支付字段表单public function payment_fields() { // 在支付表单前添加一些信息 if ( $this->description ) { // 你可以说明测试模式,显示测试之类的。 if ( $this->testmode ) { $this->description .= ' TEST MODE ENABLED. In test mode, you can use the card numbers listed in <a href="#">documentation</a>.'; $this->description = trim( $this->description ); } // 显示带有<p>标签的描述等。 echo wpautop( wp_kses_post( $this->description ) ); } // 我将用echo()的形式,你也可以直接在HTML中写 echo '<fieldset id="wc-' . esc_attr( $this->id ) . '-cc-form" class="wc-credit-card-form wc-payment-form" style="background:transparent;">'; // 如果你想让你的自定义支付网关支持这个动作,请添加这个动作钩子 do_action( 'woocommerce_credit_card_form_start', $this->id ); // #ccNo, #expdate, #cvc自己改成自己的 echo '<div class="form-row form-row-wide"><label>Card Number <span class="required">*</span></label> <input id="kekc_cn_ccNo" type="text" autocomplete="off"> </div> <div class="form-row form-row-first"> <label>Expiry Date <span class="required">*</span></label> <input id="kekc_cn_expdate" type="text" autocomplete="off" placeholder="MM / YY"> </div> <div class="form-row form-row-last"> <label>Card Code (CVC) <span class="required">*</span></label> <input id="kekc_cn_cvv" type="password" autocomplete="off" placeholder="CVC"> </div> <div class="clear"></div>'; do_action( 'woocommerce_credit_card_form_end', $this->id ); echo '<div class="clear"></div></fieldset>'; }{card-default label="效果" width="80%"}{/card-default}处理付款验证字段像名字这样的结帐字段应该更早验证,下面是一个例子。public function validate_fields(){ if( empty( $_POST[ 'billing_first_name' ]) ) { wc_add_notice( 'First name is required!', 'error' ); return false; } return true; }变更订单状态使用API获取付款并设置订单状态public function process_payment( $order_id ) { global $woocommerce; // 根据订单id获取订单明细 $order = wc_get_order( $order_id ); /* * 带有参数的数组,用于API交互 */ $args = array( ... ); /* * API交互可以用wp_remote_post()来构建 */ $response = wp_remote_post( '{payment processor endpoint}', $args ); if( !is_wp_error( $response ) ) { $body = json_decode( $response['body'], true ); // 它可能是不同的,这取决于你的支付处理程序 if ( $body['response']['responseCode'] == 'APPROVED' ) { // 我们收到付款 $order->payment_complete(); $order->reduce_order_stock(); // 给客户备注。 $order->add_order_note( '您的订单已经支付了! 谢谢你!', true ); // 空购物车 $woocommerce->cart->empty_cart(); // 重定向到感谢页面 return array( 'result' => 'success', 'redirect' => $this->get_return_url( $order ) ); } else { wc_add_notice( '请重试!', 'error' ); return; } } else { wc_add_notice( '连接失败。', 'error' ); return; } }
2024年08月10日
24 阅读
0 评论
0 点赞
2024-08-09
zencart商城对接日本支付通道
前言当前用zencart商城的比较少了,最近又接到一个新的需求。为zencart商城对接一个日本的本地支付通道。原先为zencart商城开发过一个支付插件,拿来改造一下,记录改造过程。{card-default label="支付方式" width="80%"}{/card-default}核心代码支付方式选择后,组织参数,提交到上游api,均通过unionpaySubmitOrder.php 文件完成。订单提交//提交参数 $parmsa = array( "ShopID" => $data['MerNo'], "ShopPass" => $data['Md5Key'], "OrderID" => $data['BillNo'], "JobCd" => 'CAPTURE', "Amount" => $data['Amount'], "Tax" => '0' ); $req_api_a = "https://p01.mul-pay.jp/payment/EntryTranUnionpay.idPass"; //获取支付链接 $resa = curlRemote($req_api_a, $parmsa); //将返回转换为数组 $resa_data = stringToArray($resa); //构造函数 $parmsb = array( "ShopID" => $data['MerNo'], "ShopPass" => $data['Md5Key'], "OrderID" => $data['BillNo'], "AccessID" => $resa_data['AccessID'], "AccessPass" => $resa_data['AccessPass'], "RetURL" => $data['ReturnURL'], "ErrorRcvURL" => $data['ReturnURL'], ); $req_api_b = 'https://p01.mul-pay.jp/payment/ExecTranUnionpay.idPass'; //获取支付链接 $resb = curlRemote($req_api_b, $parmsb); //将返回转换为数组 $resb_data = stringToArray($resb);自动跳转,模版渲染获取resb_data数据内,含有支付所需的token和一次性使用密钥。通过js提交到响应接口。此功能通过php模版渲染功能完成。<?php if(!defined('VERSION_INFO')){ exit; } ?> <html> <head> <title><?php echo varGet($data, 'L_SUBMIT_ORDER_CONFIRM_TITLE'); ?></title> <meta http-equiv="Content-Type" content="text/html; charset=Windows-31J"> </head> <body OnLoad='OnLoadEvent();'> <form name="UnionpayStartCall" action="<?php echo varGet($resb_data, 'StartURL'); ?>" method="POST"> <noscript> hello; <br> <br> <center> <h2>ネット銀聯の決済画面へ遷移します。</h2> <input type="submit" value="続行"> </center> </noscript> <input type="hidden" name="AccessID" value="<?php echo varGet($resb_data, 'AccessID'); ?>"> <input type="hidden" name="Token" value="<?php echo varGet($resb_data, 'Token'); ?>"> </form> <script> <!-- function OnLoadEvent() { document.UnionpayStartCall.submit(); } //--> </script> </body> </html>插件设置插件设置界面{card-default label="插件设置" width="80%"}{/card-default}
2024年08月09日
41 阅读
0 评论
0 点赞
2024-07-31
扫码点餐系统管理后台界面
前言前几天搭建部署了扫码点餐平台,继续介绍平台的功能。本文主要分享管理员后台的相关界面首页登录系统后首先看到的是首页仪表盘,包含一些系统信息。{card-default label="首页仪表盘" width="85%"}{/card-default}设置设置包括站点设置、登录注册、功能设置、分佣设置、消息提醒、友情链接等{card-default label="设置界面" width="85%"}{/card-default}
2024年07月31日
173 阅读
0 评论
0 点赞
2024-07-28
餐厅扫码点餐平台搭建部署过程
前言扫码点餐越来越流行,最近接了一个新的项目。为某餐厅上一套扫码点餐系统。记录整个部署过程。{card-default label="系统介绍" width="80%"}{/card-default}{card-describe title="源码介绍"}本框架是基于ThinkPHP的多应用模式所开发的,采用MVC的设计模式,每个模块分为三层(模型M、视图V、控制器C)。默认应用模块:common、admin、agent、user、index、applet、api、store{/card-describe}环境要求,均采用docker方式启动:PHP版本 >= 7.4 (推荐PHP7.4版本)MySql版本 >= 5.6 (需支持innodb引擎)Apache版本 >= 2.4以上 或 Nginx >= 1.10(推荐使用宝塔等集成环境)其它:服务器支持https,必须安装SSL证书,否则会影响接口的通信。部署过程详细部署过程,有专门的文档。 hemaPHP ,本文只记录部署过程中遇到的问题。构建php的docker镜像docker的官网被封了,需要搭建自己的私有源镜像。docker login --username=xwzy1130 registry.cn-hangzhou.aliyuncs.com #推送 docker tag 8933d3e7e14b registry.cn-hangzhou.aliyuncs.com/mybud/php74:lastest docker push registry.cn-hangzhou.aliyuncs.com/mybud/php74:lastest # 引用 docker pull registry.cn-hangzhou.aliyuncs.com/mybud/php74:lastestnginx配置nginx/services/nginx/conf/conf.d/hema_saas.confserver { listen 802; server_name 0.0.0.0; root /www/web/hema_saas/public; index index.html index.htm index.php; charset utf-8; access_log /www/web_logs/dcb.log wwwlogs; error_log /www/web_logs/dcb.err notice; server_tokens off; client_max_body_size 50m; error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } location / { if (!-e $request_filename) { rewrite ^(.*)$ /index.php?s=/$1 last; break; } } location ~ \.php$ { fastcgi_pass 10.0.16.8:9000; fastcgi_index index.php; include fcgi.conf; fastcgi_buffers 8 4K; fastcgi_buffer_size 4K; } location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 30d; } location ~ .*\.(js|css)?$ { expires 12h; } }
2024年07月28日
109 阅读
0 评论
0 点赞
2024-05-13
woocommerce在checkout页面自定义输入内容
关于对接第三方支付的过程中,有几个字段需要客户端上传。需要在checkout页面让客户输入然后提交。
2024年05月13日
104 阅读
0 评论
0 点赞
2024-02-01
零基础利用chatgpt两天手写一个go客户端程序
前言pc客户端程序的编写一直是我从未涉足过的领域。最近有了需求,需要写一个pc客户端运行的程序。功能要求简单,实现文件上传即可。不过不想麻烦,想着费一边事。就可以跨平台,运行。直接问chatgpt采用什么方案。最终选择了go语言,编译出来的执行文件很小,还支持交叉编译。{card-default label="程序界面" width="75%"}{/card-default}环境配置作者原先还没有go环境,先安装好go环境。然后问chatgpt运行helloworld示例程序。{card-default label="helloword" width="75%"}{/card-default}程序开发生成带界面的helloword直接问chatgpt。{card-default label="界面hello" width="75%"}{/card-default}功能函数还是将想法直接和chatgpt交流,把chatgpt的返回,复制到代码中。调试,运行。直到整个代码的完成。最终的代码一共308行。几乎全部是chatgpt返回。中间解决了几个代码问题。有时候chatgpt的返回,总是不正确,需要用搜索引擎去寻找答案。{card-default label="代码行数" width="75%"}{/card-default}
2024年02月01日
314 阅读
0 评论
0 点赞
2024-01-08
wordpress外贸独立站对接第三方支付通道easylink
前言做跨境电商如何收款是所有商家都需要关注的。自由度最高的是基于wordpress的外贸独立站,独立站建好以后需要对接收款通道。easylink是香港的支付通道。下面分享对接过程。{card-default label="支付引导" width="75%"}{/card-default}支付流程交易流程是指访问网站的客户从选择商品下单到支付成功的整个流程。{card-default label="支付流程" width="80%"}{/card-default}插件开发熟悉整个流程后,就要根据通道提供的接口文档编写代码。代码编写的主要模块有签名函数,有订单提交,异步通知处理,同步跳转函数等。签名本通道采用sha256加密方式function buildMysign($sort_para, $key, $sign_type = "MD5") { $prestr = createLinkstring ( $sort_para ); $prestr = $prestr .'&'. $key; $mysgin = sign ( $prestr, $sign_type ); return $mysgin; } function createLinkstring($para) { $arg = ""; foreach ($para as $key => $val) { if ($key == "accessKey" || $key == "merchantCardNumber" || $key == "BankId" || $key == "merReserved") continue; else $arg .= $key . "=" . $val . "&"; } $arg = rtrim($arg, '&'); return $arg; } function paraFilter($para) { $para_filter = array (); foreach ($para as $key => $val) { $para_filter [$key] = $para [$key]; } return $para_filter; } function argSort($para) { ksort ( $para ); reset ( $para ); return $para; } function sign($prestr, $sign_type = 'MD5') { $sign = ''; $sign = hash($sign_type, $prestr); return $sign; }订单提交订单提交是组织好官方需要的字段,通过api接口提交并获取结果class Submit { function buildRequestPara($para_temp) { $key = '********'; $sign_method = 'SHA256'; $para_filter = paraFilter($para_temp); $para_sort = argSort($para_filter); $mysign = buildMysign($para_sort, trim($key), strtoupper(trim($sign_method))); $para_sort['accessKey'] = $mysign; return $para_sort; } function getMsg($para_temp, $gateway) { $respondData = ''; $para = $this->buildRequestPara($para_temp); $ch = curl_init ($gateway); curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true); curl_setopt ( $ch, CURLOPT_BINARYTRANSFER, true); curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt ( $ch, CURLOPT_POSTFIELDS, $para); $output = curl_exec ( $ch ); curl_close ( $ch ); $respondData = json_decode($output); return $respondData; } }异步通知在用户支付成功后,通道会主动发起支付成功的通知到网站。需要专门的函数来处理支付结果。 function check_easylink_ipn_response() { global $woocommerce, $wpdb; require_once("lib/notify.class.php"); if (($_SERVER['REQUEST_METHOD'] === 'POST') && preg_match("/wc_easylink_notify/i", $_SERVER['REQUEST_URI'])) { $Notify = new Notify(); $verify_result = $Notify->verifyNotify(); if ( $verify_result ) { if ($_POST["respCode"] != "00") { error_log(__METHOD__ . PHP_EOL . $_POST["respMsg"]); } elseif ( $_POST['status'] == '1' ) { $sref = $_POST['paymentId']; $statustr = $this->easylink_processing; $check_query = $wpdb->get_results("SELECT order_id,order_state,mref FROM {$wpdb->prefix}easylink_data WHERE sref = '".addslashes($sref)."'", ARRAY_A); $check_query_count = count($check_query); if( $check_query_count >= 1 ) { if($check_query[0]['order_state'] == 'I') { $query = "update {$wpdb->prefix}easylink_data set order_state='C' where sref='".addslashes($sref)."'"; $wpdb->query($query); $inv_id = $check_query[0]['order_id']; $mref = $check_query[0]['mref']; $order = new WC_Order($inv_id); $order->update_status($statustr, __('Order has been paid by ID: ' . $mref, 'easylink-for-woocommerce')); wc_reduce_stock_levels( $order->get_id() ); add_post_meta( $inv_id, '_paid_date', current_time('mysql'), true ); update_post_meta( $inv_id, '_transaction_id', wc_clean($mref) ); $order->payment_complete(wc_clean($mref)); $woocommerce->cart->empty_cart(); } } } } //接口返回 exit('success'); } }同步跳转在网站处理支付成功的消息的同时,客户浏览器需要跳转到支付成功页面。function check_easylink_return() { global $woocommerce, $wpdb; if (($_SERVER['REQUEST_METHOD'] === 'GET') && preg_match("/wc_easylink_return/i", $_SERVER['REQUEST_URI'])) { //error_log(__METHOD__ . PHP_EOL .print_r($_GET, true)); $mref = $_GET['mref']; sleep(1); $check_query = $wpdb->get_results("SELECT order_id,order_state FROM {$wpdb->prefix}easylink_data WHERE mref = '".addslashes($mref)."'", ARRAY_A); $check_query_count = count($check_query); if($check_query_count >= 1){ $inv_id = $check_query[0]['order_id']; $inv_state = $check_query[0]['order_state']; switch ( $inv_state ) { case 'C': $order = new WC_Order($inv_id); wp_redirect(esc_url_raw(add_query_arg('key', $order->get_order_key(), add_query_arg('order-received', $inv_id, $this->get_return_url($order))))); break; default: wp_redirect( wc_get_cart_url() ); } exit; } } wp_redirect(home_url()); }完整的支付插件【支付插件】woocommerce对接香港支付通道easylink插件设置插件安装通过wordpress的后台页面上传然后激活即可,设置也非常简单。{card-default label="插件设置" width="80%"}{/card-default}
2024年01月08日
574 阅读
0 评论
0 点赞
2023-12-22
woocommerce对接第四方支付通道okpay
前言用wordpress+woocommerce做跨境独立站的朋友为了顺利收款,会对接各种国外的本地收款渠道。主流的用paypal等,不过通道越大。合规查的越严,小众的一些三方或四方通道,限制也会小一点。本文分享菲律宾四方通道okpay的对接过程。{card-default label="收银台" width="75%"}{/card-default}对接流程一般都是申请通道账号,根据接口文档开发插件,然后测试调试,通过后上线。支付插件主要有三个函数和签名函数。三个函数为提交订单信息获取支付链接,异步通知处理,同步跳转处理函数。核心代码md5签名函数 public function get_sign($srcArray, $merKey){ if(null == $srcArray){ return "123456"; } //先干掉sign字段 $keys = array_keys($srcArray); $index = array_search("sign", $keys); if ($index !== FALSE) { array_splice($srcArray, $index, 1); } //对数组排序 ksort($srcArray); //生成待签名字符串 $srcData = ""; foreach ($srcArray as $key => $val) { if($val === null || $val === "" ){ //值为空的跳过,不参与加密 continue; } $srcData .= "$key=$val" . "&"; } $srcData = substr($srcData, 0, strlen($srcData) - 1); //生成签名字符串 $sign = md5($srcData.$merKey); return $sign; }post提交函数 public function http_post($url, $sendInfo) { try { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60); curl_setopt($ch, CURLOPT_TIMEOUT, 60); // Set headers for JSON content curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json', 'Accept: application/json' )); // Encode $sendInfo as JSON $json_data = json_encode($sendInfo); curl_setopt($ch, CURLOPT_POSTFIELDS, $json_data); $curl_result = curl_exec($ch); curl_close($ch); return $curl_result; } catch (Exception $e) { return null; } }支付成功后异步回调处理函数 if (($_SERVER['REQUEST_METHOD'] === 'POST') && preg_match("/wc_okpay_notify/i", $_SERVER['REQUEST_URI'])) { $response = file_get_contents("php://input"); error_log(__METHOD__ . PHP_EOL .print_r($response, true)); //参数 $respj = json_decode($response, true, 512, JSON_BIGINT_AS_STRING); //error_log(__METHOD__ . PHP_EOL .print_r($respj['data'], true)); if ($respj['data']) { //组织签名串 //$res_sign = $this->get_sign($_POST, $this->okpay_merchant_key); #订单号 $mref = $respj['data']['orderNo']; $sref = $respj['data']['businessNo'];; #写入数据库 $query = "update {$wpdb->prefix}okpay_data set order_state = 'C' where mref = '".addslashes($mref)."'"; $wpdb->query($query); #后续处理 $check_query = $wpdb->get_results("SELECT order_id FROM {$wpdb->prefix}okpay_data WHERE mref = '".addslashes($mref)."'", ARRAY_A); $check_query_count = count($check_query); if($check_query_count >= 1){ $order_id= $check_query[0]['order_id']; $order = new WC_Order($order_id); $statustr = $this->okpay_processing; $order->update_status($statustr, __('Order has been paid by ID: ' . $sref, 'okpay-for-woocommerce')); wc_reduce_stock_levels( $order->get_id() ); add_post_meta( $order_id, '_paid_date', current_time('mysql'), true ); update_post_meta( $order_id, '_transaction_id', wc_clean($order_id) ); $order->payment_complete(wc_clean($order_id)); $woocommerce->cart->empty_cart(); } }项目完整代码【支付插件】woocommerce对接第三方支付接口okpay
2023年12月22日
406 阅读
0 评论
0 点赞
1
2
...
9