CRMEB开源商城系统是一款全开源可商用的系统,前后端分离开发,全部100%开源,在小程序、公众号、H5、APP、PC端都能用,使用方便,二开方便!
本章内容主要讲解crmeb接入上海汇付支付平台的在线支付功能。汇付支付可以完美解决crmeb在小程序、公众号、H5、APP、PC端上的支付服务。
以下以微信小程序的对接为例,首先需要在rcmeb里引入汇付官方的PHP版SDK,然后再开发支付接口,代码如下:
namespace crmeb\services\pay\storage;
use app\services\pay\PayServices;
use crmeb\exceptions\AdminException;
use crmeb\exceptions\PayException;
use crmeb\services\pay\BasePay;
use crmeb\services\pay\PayInterface;
use crmeb\services\pay\extend\huifupay\HuifuPay as HuifuPayService;
use EasyWeChat\Payment\Order;
use think\facade\Event;
use think\facade\Log;
/**
* 汇付天下
* Class HuifuPay
* @author 模板之家
* @email 75283535@qq.com
* @date 2024/05/10
* @package crmeb\services\pay\storage
*/
class HuifuPay extends BasePay implements PayInterface
{
/**
* @var HuifuPayService
*/
protected $pay;
/**
* @param array $config
* @return mixed|void
* @author 模板之家
* @email 75283535@qq.com
* @date 2023/1/15
*/
protected function initialize(array $config)
{
$this->pay = new HuifuPayService([
'sys_id' => sys_config('sys_id'),
'product_id' => sys_config('product_id'),
'huifu_id' => sys_config('huifu_id'),
'rsa_merch_private_key' => sys_config('rsa_merch_private_key'),
'rsa_huifu_public_key' => sys_config('rsa_huifu_public_key'),
'notify_url' => trim(sys_config('site_url')) . '/api/pay/notify/huifu',
]);
}
/**
* 创建支付
* @param string $orderId
* @param string $totalFee
* @param string $attach
* @param string $body
* @param string $detail
* @param array $options
* @return array|mixed
* @author 模板之家
* @email 75283535@qq.com
* @date 2023/1/15
*/
public function create(string $orderId, string $totalFee, string $attach, string $body, string $detail, array $options = [])
{
$this->authSetPayType();
$options['returl'] = sys_config('site_url') . '/pages/index/index';
if ($options['returl']) {
$options['returl'] = str_replace('http://', 'https://', $options['returl']);
}
$options['appid'] = sys_config('routine_appId');
$notifyUrl = trim(sys_config('site_url')) . '/api/pay/notify/huifu' . $attach;
$this->pay->setNotifyUrl($notifyUrl);
switch ($this->payType) {
case Order::JSAPI:
return $this->pay->miniproPay($totalFee, $orderId, $body, $attach, $options['openid'] ?? '');
default:
throw new PayException('汇付天下:暂不支持此环境下支付');
}
}
public function merchantPay(string $openid, string $orderId, string $amount, array $options = [])
{
throw new PayException('汇付天下:暂不支持商家转账');
}
/**
* 发起退款
* @param string $outTradeNo
* @param array $options
* @return array|mixed
* @author 模板之家
* @email 75283535@qq.com
* @date 2023/1/15
*/
public function refund(string $outTradeNo, array $options = [])
{
$result = $this->pay->refund($options['refund_price'], $options['order_id'], $options['org_req_date'], $outTradeNo);
if ($result['resp_code'] == '00000100') {//如果交易正在进行的话,就要查询交易结果
$maxAttempts = 10; // 最大尝试次数
$attempts = 0; // 当前尝试次数
$retData = null; // 初始化数据变量
// 当没有数据或者数据为空时,反复请求
while ($retData === null && $attempts < $maxAttempts) {
// 执行数据请求
$retData = $this->refundQuery($options['order_id'], $result['org_req_date']);
// 如果没有数据,等待一段时间后重试
if ($retData === null || $retData['trans_stat'] == 'P') {
sleep(2); //等待2秒
$attempts++;
} else {
break;
}
if ($retData && $retData['trans_stat'] == 'F') {
throw new PayException($retData['bank_message']);
}
if ($retData && $retData['trans_stat'] == 'S') {
break;
}
if ($retData && $retData['trans_stat'] == 'I') {
throw new PayException($retData['bank_message']);
}
}
}
if ($result['resp_code'] != '00000000' && $result['resp_code'] != '00000100') throw new AdminException($result['resp_desc']);
}
public function refundQuery(string $org_req_seq_id, string $org_req_date)
{
$result = $this->pay->refundQuery($org_req_seq_id, $org_req_date);
return $result;
}
public function queryRefund(string $outTradeNo, string $outRequestNo, array $other = [])
{
// TODO: Implement queryRefund() method.
}
/**
* 支付异步回调
* @return mixed|string
* @author 模板之家
* @email 75283535@qq.com
* @date 2023/1/15
*/
public function handleNotify(string $attach = '')
{
$attach = str_replace('huifu', '', $attach);
return $this->pay->handleNotify(function ($notify) use ($attach) {
if (isset($notify['req_seq_id'])) {
$data = [
'attach' => $attach,
'out_trade_no' => $notify['req_seq_id'],
'transaction_id' => $notify['hf_seq_id']
];
return Event::until('NotifyListener', [$data, PayServices::HUIFU_PAY]);
}
return false;
});
}
/**
* 退款异步回调
* @return mixed|string
* @author 模板之家
* @email 75283535@qq.com
* @date 2023/1/15
*/
public function refundNotify(string $attach = '')
{
$attach = str_replace('huifu', '', $attach);
return $this->pay->refundNotify(function ($notify) use ($attach) {
if (isset($notify['req_seq_id'])) {
$data = [
'attach' => $attach,
'out_trade_no' => $notify['req_seq_id'],
'transaction_id' => $notify['hf_seq_id']
];
return Event::until('NotifyListener', [$data, PayServices::HUIFU_PAY]);
}
return false;
});
}
}
汇付支付SDK获取地址:
https://github.com/huifurepo/bspay-php-sdk
官方SDK要导入crmeb,需要改良部分功能,否则无法正常导入到crmeb项目中,我当初对接时,在这里耽搁了不少时间,最后发现是汇付的SDK不太完善,需要开发者改良。因开发内容较多,在这里就不帖出全部代码了,欢迎各位开发者加我(V:xu08290201)一起交流开发经验。汇付支付对于退款接口等是有异步回调通知的,但crmeb本身只在支付交易中有异步通知,所以开发者需要自行再开发退款异步通知接口。好了,大概就写这些吧,大家在开发中有遇到问题,可以私信联系,一起共享交流。