当前位置: 首页 > news >正文

Ksher H5页面支付实例指导 (PHP实现)

前文

  • 背景介绍
    前两天,公司的项目,为了满足泰国客户的支付需求,要求使用 Ksher (开时支付)
    对接任务突然就给了鄙人,一脸懵 …
    通过了解客户的使用场景、以及参考官网指导
    发现:Ksher支付 最令人满意的便是 —— 提供了便捷的 支付 Demo
    在此,做下梳理,希望能对小伙伴有所帮助,欢迎指摘 …

  • 场景要求

满足 在手机 H5 页面,能在商品下单后,弹出支付二维码 (promptPay、trueMoney、card、wechat) , 引导去支付

  • 简单介绍
  Ksher 成立于 2016 年,由红杉资本和 Infinity 投资,在 11 个国家设立运营公司,聚焦东南亚,为全球 150,000+ 企业提供支付服务。ksher 专注东南亚市场、深耕出口卖家生态,帮助中国卖家安全、高效、便捷地处理东南亚电商结算货款

  • 官方文档

【API 开发文档 >>>】
【SDK Support >>> 】 (满足 Java、Python、Go、PHP、Netcore、NodeJs


☛ 开发步骤

当前需求,是要满足 在手机 H5 页面,能在商品下单后,弹出支付二维码 (promptPay、trueMoney、card、wechat) , 引导去支付

①. 确认支付场景,选取参考代码

以我的场景需求和实际操作,想实现 H5页面的 Ksher支付,那么参考 【PHP - SDK Demo >>>】 中的 gateway_pay(WebSite) 这一部分即可

  • demo 演示页面如下:

②. 代码整合SDK

以我使用的 Yii2 框架 为例,将 php-sdk 文件放在了 common目录

  • 在提取使用时,其实就是对 ksher_pay_sdk.php 文件的 KsherPay类的使用
    为了避免直接改动 sdk 文件(方便出错排查),
    我复制了一份 ksher_pay_sdk文件,稍作个文件名和命名空间变动即可:

③. 实现下单流程

提取核心 下单逻辑代码,封装处理如下

    /*** @Notes:处理获取 Ksher支付数据 (gateway_pay 方式)* @param string $ksher_pay_order_sn	唯一的订单编号* @param int $ksher_sum_pay_amount		订单金额,例:25.50* @return array* @User: zhanghj* @DateTime: 2023-12-22 11:57*/public function dealGetKsherGatewayPayData($ksher_pay_order_sn = '',$ksher_sum_pay_amount = 0){$err_msg = '';$ksher_data = [];$ks_appid = PayMzConfig::KSHER_APP_ID;$ks_privatekey = PayMzConfig::KSHER_PRIVATE_KEY;$class = new KsherPay($ks_appid,$ks_privatekey);$gateway_pay_data = array('mch_order_no' => $ksher_pay_order_sn,"total_fee" => round($ksher_sum_pay_amount, 2) * 100,"fee_type" => 'THB',    //默认为泰铢"channel_list" => 'promptpay,truemoney,card,wechat',   //支付方式 wechat'mch_code' => $ksher_pay_order_sn,'mch_redirect_url' => 'http://www.ksher.cn','mch_redirect_url_fail' => 'http://www.ksher.cn','product_name' => PayMzConfig::KSHER_SHOW_PAY_PRODUCT_NAME,'refer_url' => 'http://www.ksher.cn',"mch_notify_url" => PayMzConfig::KSHER_H5_ORDER_PAY_NOTIFY,'device' => 'H5' //H5(手机端)、PC(电脑端));$gateway_pay_response = $class->gateway_pay($gateway_pay_data);$gateway_pay_array = json_decode($gateway_pay_response, true);if (isset($gateway_pay_array['data']['pay_content'])) {$ksher_data['pay_link'] = $gateway_pay_array['data']['pay_content']??'';}else{$failed_msg = $gateway_pay_array['msg']??'';$failed_message = $gateway_pay_array['message']??'';$failed_message = empty($failed_message)?(LanguageMz::CHECK_KSHER_PAY_AWAKE_FAILED):$failed_message;$err_msg = $failed_msg?$failed_msg:$failed_message;}return [$err_msg,$ksher_data];}
  • 重点是得到上面的 pay_link 数据,整理反馈给前端数据形式如下:
{"code": 200,"msg": "操作成功","data": {"pay_link": "https://gateway.ksher.com/h5?order_uuid=074ad88ca3c911ee9148525400962f26&lang=en"}
}

④. 实现效果

点击前面成功生成的支付链接,会直接跳转到 Ksher 支付唤醒页面,如下为 H5 页面(PC端同理)

  • 提示: 测试发现,如果手机端使用微信打开,会默认唤醒微信支付界面,同时支付金额自动由泰铢转化为人民币

⑤. 支付回调处理

对于支付回调的处理,参考 sdk 中提供的 demo_notify.php 文件代码进行实现

  • 根据业务功能,整理支付回调接口,处理如下:
    /*** @Notes:Ksher H5订单支付回调接口 (正式)* @User: zhanghj* @DateTime: 2023-12-22 11:46*/public function actionKsherH5OrderNotify(){//1.接收参数$input = file_get_contents("php://input");$query = urldecode($input);if( !$query){//记录日志信息CommonMzService::recordLocalFileLog('ksher_pay',"NO RETURN DATA" );echo json_encode(array('result'=>'FAIL',"msg"=>'NO RETURN DATA'));exit;}//2.验证参数$data_array = json_decode($query,true);CommonMzService::recordLocalFileLog('ksher_pay',"notify data :".json_encode( $data_array) );if( !isset( $data_array['data']) || !isset( $data_array['data']['mch_order_no']) || !$data_array['data']['mch_order_no']){echo json_encode(array('result'=>'FAIL',"msg"=>'RETURN DATA ERROR'));exit;}//3.处理订单if( array_key_exists("code", $data_array)&& array_key_exists("sign", $data_array)&& array_key_exists("data", $data_array)&& array_key_exists("result", $data_array['data'])&& $data_array['data']["result"] == "SUCCESS"){$ks_appid = PayMzConfig::KSHER_APP_ID;$ks_privatekey = PayMzConfig::KSHER_PRIVATE_KEY;$class = new KsherPay($ks_appid,$ks_privatekey);//3.1验证签名$verify_sign = $class->verify_ksher_sign($data_array['data'], $data_array['sign']);if( $verify_sign==1 ){//更新订单信息 change order status$pay_order_sn = $data_array['data']['mch_order_no'];$channel = $data_array['data']['channel']??'';$total_fee = $data_array['data']['total_fee']??'';$payment_json_str = json_encode($data_array,JSON_UNESCAPED_UNICODE);//TODO 此处为我的业务处理,可根据自己的业务,替换更新 ...(new PayMzService())->dealUpdateKsherGatewayPayOrder($pay_order_sn,$payment_json_str,$channel,$total_fee);echo json_encode(array('result'=>'SUCCESS',"msg"=>'OK'));} else {CommonMzService::recordLocalFileLog('ksher_pay','VERIFY_KSHER_SIGN_FAIL');echo json_encode(array('result'=>'Fail',"msg"=>'VERIFY_KSHER_SIGN_FAIL'));}}}

附录

1. 为什么 手机端的 H5 页面支付场景会是 显示支付二维码?

  通过了解,泰国常用的APP并非微信、支付宝,他们常用的支付APP 为 promptPay、trueMoney、VISA 等在H5页面,可以截图需要支付的二维码,打开支付APP,进行识别支付即可个人感觉,没有微信(国内)和支付宝使用方便

2. 源代码中,提到的 PayMzConfig 为支付配置类,方便后期对 Ksher 支付配置信息的改动

  • 摘取部分代码如下:
<?php
namespace common\enum;
/*** Mz 专用开发配置* Class PayMzConfig* @package common\enum*/
class PayMzConfig {//=================Ksher支付配置=============const KSHER_APP_ID = 'mch4XXXX';    //应用ID//私钥const KSHER_PRIVATE_KEY = <<<EOD
-----BEGIN RSA PRIVATE KEY-----
MIICYAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXGk34+n
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
u9UlGXXXXXXXXXXXXXXXXXXXXXXXXXXXXp9xJa
-----END RSA PRIVATE KEY-----
EOD;const KSHER_SHOW_PAY_PRODUCT_NAME = 'HWAPPU-Water';//TODO 配置为自己的支付回调接口const KSHER_H5_ORDER_PAY_NOTIFY = 'http://clientapi.xxxxx.com/notify/ksher_h5_order_notify';
}

3. 对于支付回调接口中提到的recordLocalFileLog()方法,可根据自己的代码,放在合适位置

    /*** @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());if( !$log_content ) return false;if ($op_type == 'ksher_pay'){$log_file_name = 'ksher_pay';}else{$log_file_name = 'mz';}$file = dirname(Yii::$app->basePath)."/api/log/{$log_file_name}_".date("Ymd").".txt";$handle = fopen( $file, 'a+');fwrite( $handle , "[{$time_stamp}]: ".$log_content."\r");fclose( $handle );}

相关文章:

  • C语言——最古老的树
  • java基础之String、StringBuilder、StringBuffer的异同
  • Mysql(5日志备份恢复)
  • [Linux]Ubuntu noVNC使用
  • linux 休眠唤醒中设备、总线、用户进程、内核线程调试分析流程
  • arkts中@Watch监听的使用
  • [年终总结]人生就是大闹一场
  • 为什么不应该在 SAN/NAS 设备上运行 MinIO(还有一个例外)
  • 【机器学习】人工智能概述
  • Mysql 高级语句
  • P5729 【深基5.例7】工艺品制作题解
  • 数据资源将被视为资产 明天起纳入财务报表
  • 防火墙双机热备配置步骤
  • ubuntu22.04 安装jdk8,jdk11,jdk17,jdk21 并且便于切换
  • Springcloud Alibaba使用Canal将Mysql数据实时同步到Redis保证缓存的一致性
  • cookie和session
  • github从入门到放弃(1)
  • Java-详解HashMap
  • Phpstorm怎样批量删除空行?
  • Python3爬取英雄联盟英雄皮肤大图
  • ubuntu 下nginx安装 并支持https协议
  • 第十八天-企业应用架构模式-基本模式
  • 今年的LC3大会没了?
  • 京东美团研发面经
  • 深度学习中的信息论知识详解
  • 跳前端坑前,先看看这个!!
  • 微信如何实现自动跳转到用其他浏览器打开指定页面下载APP
  • 吴恩达Deep Learning课程练习题参考答案——R语言版
  • 小程序上传图片到七牛云(支持多张上传,预览,删除)
  • 怎么把视频里的音乐提取出来
  • ​Kaggle X光肺炎检测比赛第二名方案解析 | CVPR 2020 Workshop
  • ​草莓熊python turtle绘图代码(玫瑰花版)附源代码
  • #14vue3生成表单并跳转到外部地址的方式
  • #Z2294. 打印树的直径
  • (8)Linux使用C语言读取proc/stat等cpu使用数据
  • (BFS)hdoj2377-Bus Pass
  • (C语言)fread与fwrite详解
  • (Oracle)SQL优化技巧(一):分页查询
  • (poj1.3.2)1791(构造法模拟)
  • (二)构建dubbo分布式平台-平台功能导图
  • (二)学习JVM —— 垃圾回收机制
  • (论文阅读30/100)Convolutional Pose Machines
  • (四)docker:为mysql和java jar运行环境创建同一网络,容器互联
  • (一)使用IDEA创建Maven项目和Maven使用入门(配图详解)
  • (转)关于pipe()的详细解析
  • ****** 二十三 ******、软设笔记【数据库】-数据操作-常用关系操作、关系运算
  • .NET 4.0中使用内存映射文件实现进程通讯
  • .Net 6.0 处理跨域的方式
  • .NET Core 和 .NET Framework 中的 MEF2
  • .Net Core与存储过程(一)
  • .net framwork4.6操作MySQL报错Character set ‘utf8mb3‘ is not supported 解决方法
  • .Net Remoting常用部署结构
  • .NET 设计模式—简单工厂(Simple Factory Pattern)
  • .NET 中什么样的类是可使用 await 异步等待的?
  • .NET企业级应用架构设计系列之开场白