一、服务端修改(PHP示例)
1. 新增拉卡拉支付驱动
文件路径:app/services/pay/LakalaPay
<?php
namespace app\services\pay;
use think\facade\Config;
class LakalaPayService
{
private $merchantId; // 商户ID
private $apiKey; // API密钥
private $apiUrl = 'https://openapi.lakala.com'; // 正式环境地址
public function __construct()
{
$config = Config::get('payment.lakala');
$this->merchantId = $config['merchant_id'];
$this->apiKey = $config['api_key'];
}
/**
* 创建收银台订单
* @param array $order 订单数据(需包含order_id,price,title等)
*/
public function createOrder($order)
{
$params = [
'merchant_order_no' => $order['order_id'],
'amount' => bcmul($order['price'], 100), // 转为分
'subject' => mb_substr($order['title'], 0, 32), // 截断防超长
'source' => 'WECHATMINI',
'notify_url' => request()->domain() . '/api/lakala/notify',
'extra' => json_encode(['user_id' => $order['uid']])
];
$result = $this->httpPost('/v3/ccss/counter/order/special_create', $params);
if ($result['code'] != 200) {
throw new \Exception('拉卡拉下单失败:' . $result['msg']);
}
return $result['data']['counter_url']; // 返回收银台URL
}
private function httpPost($path, $data)
{
$url = $this->apiUrl . $path;
$timestamp = time();
$sign = $this->makeSign($data, $timestamp);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Authorization: ' . $this->merchantId,
'Timestamp: ' . $timestamp,
'Signature: ' . $sign
]);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true);
}
private function makeSign($data, $timestamp)
{
ksort($data);
$queryString = http_build_query($data);
return md5($this->merchantId . $queryString . $timestamp . $this->apiKey);
}
}
2. 配置支付方式
文件路径:config/payment.php
新增配置:
'lakala' => [
'merchant_id' => env('LAKALA_MERCHANT_ID', ''),
'api_key' => env('LAKALA_API_KEY', '')
],
3. 添加支付回调处理
文件路径:app/api/controller/LakalaController.php
<?php
namespace app\api\controller;
use think\facade\Db;
class LakalaController
{
// 支付结果回调
public function notify()
{
$data = input('post.');
$sign = $this->makeSign($data, $data['timestamp']);
// 验签
if ($sign != $data['sign']) {
return json(['code' => 400, 'msg' => '签名错误']);
}
// 处理订单逻辑
Db::name('store_order')
->where('order_id', $data['merchant_order_no'])
->update([
'paid' => 1,
'pay_time' => time()
]);
return json(['code' => 200]);
}
private function makeSign($data, $timestamp)
{
// 与LakalaPayService中的签名方法一致
}
}
二、小程序端修改(Uni-app示例)
1. 支付按钮触发逻辑
文件路径:uniapp/pages/order/pay.vue
import { lakalaPay } from '@/api/pay.js';
export default {
methods: {
async handleLakalaPay() {
try {
const orderId = this.orderInfo.order_id;
const res = await lakalaPay({ order_id: orderId });
// 解析返回的counterUrl
const counterUrl = res.counter_url;
let appId = 'wx889424d565967811'; // 默认appId
// 根据域名判断小程序appId
if (counterUrl.includes('q.lakala.com')) {
appId = 'wxc3e4d1682da3053c';
}
// 跳转拉卡拉小程序
uni.navigateToMiniProgram({
appId,
path: `/payment-cashier/pages/checkout/index?source=WECHATMINI&counterUrl=${encodeURIComponent(counterUrl)}`,
success: () => {
this.startPollResult(orderId); // 开始轮询支付结果
}
});
} catch (e) {
uni.showToast({ title: e.message, icon: 'none' });
}
},
// 轮询支付结果
startPollResult(orderId) {
const timer = setInterval(async () => {
const res = await checkPayStatus(orderId);
if (res.paid) {
clearInterval(timer);
uni.redirectTo({ url: '/pages/order/result?id=' + orderId });
}
}, 3000);
}
}
}
2. 支付API封装
文件路径:uniapp/api/pay.js
import { request } from './request';
export const lakalaPay = (data) => {
return request({
url: '/api/order/lakala_pay',
method: 'POST',
data
});
};
export const checkPayStatus = (orderId) => {
return request({
url: '/api/order/check_status',
method: 'GET',
data: { order_id: orderId }
});
};
三、数据库修改
1. 新增支付方式
执行SQL:
INSERT INTO `eb_system_pay` (`name`, `icon`, `config`, `status`)
VALUES ('拉卡拉支付', 'lakala.png', '{"merchant_id":"","api_key":""}', 1);
四、关键配置项
-
小程序跳转白名单
-
在微信小程序后台配置
navigateToMiniProgram
白名单:-
wx889424d565967811
(聚合收银台) -
wxc3e4d1682da3053c
(收款宝)
-
-
-
域名配置
-
确保服务器域名
openapi.lakala.com
加入CRMEB的请求白名单
-
-
安全设置
-
拉卡拉商户平台配置
IP白名单
和回调地址
-
五、支付流程时序
图表
代码
sequenceDiagram
用户->>CRMEB: 提交订单
CRMEB->>拉卡拉: 调用special_create接口
拉卡拉-->>CRMEB: 返回counter_url
CRMEB->>小程序: 返回支付参数
小程序->>拉卡拉小程序: 跳转收银台
用户->>拉卡拉小程序: 完成支付
拉卡拉->>CRMEB: 异步回调通知
CRMEB->>数据库: 更新订单状态
小程序->>CRMEB: 轮询支付结果
CRMEB-->>用户: 显示支付成功
常见问题处理
-
收银台无法跳转
-
检查
appId
是否配置正确 -
确认小程序基础库版本≥2.2.1
-
-
签名失败
-
确保服务端和拉卡拉平台的
API密钥
一致 -
检查时间戳同步(允许±5分钟误差)
-
-
跨域问题
-
在CRMEB的
middleware.php
中添加拉卡拉域名到跨域白名单
-