
大模型RAG技術:從入門到實踐
wx.login({
success: function (res) {
if (res.code) {
// 將 code 發送到服務器端
wx.request({
url: 'https://your-server-domain.com/api/wechat/login',
method: 'POST',
data: {
code: res.code
},
success: function (res) {
// 登錄成功,保存 token
wx.setStorageSync('token', res.data.token);
},
fail: function (err) {
console.error('登錄失敗', err);
}
});
} else {
console.error('獲取 code 失敗', res);
}
}
});
// 服務器端登錄邏輯
public function wechatLogin(Request $request) {
$code = $request->input('code');
$appid = 'your-wechat-appid';
$secret = 'your-wechat-secret';
// 通過 code 獲取 openid 和 session_key
$url = "https://api.weixin.qq.com/sns/jscode2session?appid={$appid}&secret={$secret}&js_code={$code}&grant_type=authorization_code";
$response = file_get_contents($url);
$data = json_decode($response, true);
if (isset($data['openid'])) {
$openid = $data['openid'];
$user = User::where('wechat_openid', $openid)->first();
if (!$user) {
// 創建新用戶
$user = new User();
$user->wechat_openid = $openid;
$user->save();
}
// 生成 token
$token = $this->generateToken($user);
return response()->json(['token' => $token]);
} else {
return response()->json(['error' => '登錄失敗'], 400);
}
}
private function generateToken($user) {
// 生成 token 的邏輯,可以使用 JWT 或其他方式
return md5($user->id . time());
}
// 小程序端支付邏輯
wx.request({
url: 'https://your-server-domain.com/api/wechat/pay',
method: 'POST',
data: {
package_id: 1, // 套餐 ID
user_id: wx.getStorageSync('user_id')
},
success: function (res) {
const paymentData = res.data;
wx.requestPayment({
timeStamp: paymentData.timeStamp,
nonceStr: paymentData.nonceStr,
package: paymentData.package,
signType: paymentData.signType,
paySign: paymentData.paySign,
success: function (res) {
console.log('支付成功', res);
},
fail: function (err) {
console.error('支付失敗', err);
}
});
},
fail: function (err) {
console.error('生成支付訂單失敗', err);
}
});
// 服務器端支付邏輯
public function wechatPay(Request $request) {
$packageId = $request->input('package_id');
$userId = $request->input('user_id');
// 獲取套餐信息
$package = Package::find($packageId);
if (!$package) {
return response()->json(['error' => '套餐不存在'], 400);
}
// 生成訂單
$order = new Order();
$order->user_id = $userId;
$order->package_id = $packageId;
$order->amount = $package->price;
$order->status = 'pending';
$order->save();
// 調用微信支付統一下單接口
$appid = 'your-wechat-appid';
$mch_id = 'your-wechat-mch-id';
$key = 'your-wechat-api-key';
$nonceStr = md5(uniqid());
$body = '套餐購買';
$out_trade_no = $order->id;
$total_fee = $order->amount * 100; // 單位為分
$spbill_create_ip = $request->ip();
$notify_url = 'https://your-server-domain.com/api/wechat/pay/notify';
$trade_type = 'JSAPI';
$openid = User::find($userId)->wechat_openid;
$params = [
'appid' => $appid,
'mch_id' => $mch_id,
'nonce_str' => $nonceStr,
'body' => $body,
'out_trade_no' => $out_trade_no,
'total_fee' => $total_fee,
'spbill_create_ip' => $spbill_create_ip,
'notify_url' => $notify_url,
'trade_type' => $trade_type,
'openid' => $openid
];
// 生成簽名
ksort($params);
$stringA = '';
foreach ($params as $key => $value) {
$stringA .= $key . '=' . $value . '&';
}
$stringSignTemp = $stringA . 'key=' . $key;
$sign = strtoupper(md5($stringSignTemp));
$params['sign'] = $sign;
// 發送請求
$xml = $this->arrayToXml($params);
$response = $this->postXmlCurl($xml, 'https://api.mch.weixin.qq.com/pay/unifiedorder');
$result = $this->xmlToArray($response);
if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
// 返回支付參數給小程序端
$paymentData = [
'timeStamp' => time(),
'nonceStr' => $nonceStr,
'package' => 'prepay_id=' . $result['prepay_id'],
'signType' => 'MD5',
'paySign' => $this->generatePaySign($appid, $result['prepay_id'], $nonceStr, $key)
];
return response()->json($paymentData);
} else {
return response()->json(['error' => '生成支付訂單失敗'], 400);
}
}
private function arrayToXml($arr) {
$xml = "<xml>";
foreach ($arr as $key => $val) {
if (is_numeric($val)) {
$xml .= "<" . $key . ">" . $val . "</" . $key . ">";
} else {
$xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
}
}
$xml .= "</xml>";
return $xml;
}
private function xmlToArray($xml) {
libxml_disable_entity_loader(true);
$values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return $values;
}
private function postXmlCurl($xml, $url, $useCert = false, $second = 30) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, $second);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
private function generatePaySign($appid, $prepay_id, $nonceStr, $key) {
$params = [
'appId' => $appid,
'timeStamp' => (string)time(),
'nonceStr' => $nonceStr,
'package' => 'prepay_id=' . $prepay_id,
'signType' => 'MD5'
];
ksort($params);
$stringA = '';
foreach ($params as $key => $value) {
$stringA .= $key . '=' . $value . '&';
}
$stringSignTemp = $stringA . 'key=' . $key;
$sign = strtoupper(md5($stringSignTemp));
return $sign;
}
// 支付回調處理
public function wechatPayNotify(Request $request) {
$xml = file_get_contents('php://input');
$data = $this->xmlToArray($xml);
if ($data['return_code'] == 'SUCCESS' && $data['result_code'] == 'SUCCESS') {
$orderId = $data['out_trade_no'];
$order = Order::find($orderId);
if ($order && $order->status == 'pending') {
$order->status = 'paid';
$order->save();
// 更新用戶套餐信息
$user = User::find($order->user_id);
$user->package_id = $order->package_id;
$user->save();
}
return response()->xml(['return_code' => 'SUCCESS', 'return_msg' => 'OK']);
} else {
return response()->xml(['return_code' => 'FAIL', 'return_msg' => '支付失敗']);
}
}
// 發送模板消息
public function sendTemplateMessage($openid, $templateId, $data, $page = null) {
$accessToken = $this->getAccessToken();
$url = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token={$accessToken}";
$params = [
'touser' => $openid,
'template_id' => $templateId,
'page' => $page,
'data' => $data
];
$response = $this->postJsonCurl($url, $params);
return json_decode($response, true);
}
private function getAccessToken() {
$appid = 'your-wechat-appid';
$secret = 'your-wechat-secret';
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$secret}";
$response = file_get_contents($url);
$data = json_decode($response, true);
return $data['access_token'];
}
private function postJsonCurl($url, $data) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
// 套餐到期通知
public function sendPackageExpireNotice($userId) {
$user = User::find($userId);
$openid = $user->wechat_openid;
$templateId = 'your-template-id';
$data = [
'keyword1' => ['value' => '套餐即將到期'],
'keyword2' => ['value' => date('Y-m-d H:i:s', strtotime('+7 days'))],
'keyword3' => ['value' => '請及時續費']
];
$this->sendTemplateMessage($openid, $templateId, $data);
}
通過本文的介紹,你已經了解了如何將 SSPanel-Uim 與微信小程序進行對接,包括用戶登錄、支付、通知等功能的實現。這些功能的實現不僅提升了用戶體驗,還為 SSPanel-Uim 的管理和運營帶來了極大的便利。希望本文的內容能夠幫助你在實際項目中順利實現 SSPanel-Uim 與微信小程序的對接。
如果你在對接過程中遇到任何問題,歡迎在評論區留言,我們將盡力為你解答。