Step‑by‑Step Guide to Integrate WeChat Pay with Webman‑Admin
This tutorial walks you through the entire process of enabling WeChat Pay in a Webman‑Admin project, covering merchant registration, certificate handling, backend configuration, PHP code setup, front‑end JS integration, asynchronous callbacks, and logging details.
Introduction
The article provides a comprehensive tutorial for integrating WeChat Pay into the open‑source Webman‑Admin backend framework.
Prerequisites
Apply for a WeChat Pay merchant account via the official portal.
Obtain the merchant number and set up an authorized domain (format http://yourdomain/).
Certificate Acquisition
Log in to the WeChat merchant platform.
Retrieve the merchant ID.
Add the payment authorization domain.
Install any required certificates as prompted.
Configure API security settings.
Apply for an API certificate (skip if already available).
Generate the API certificate and download it.
Extract the certificate package and keep the _cert.zip file.
Verify the merchant ID and name, then proceed.
Copy the certificate content using the provided tool.
Open the merchant platform in a browser.
Copy the certificate string.
Switch to the certificate utility.
Inspect the certificate folder.
Save the certificate files (e.g., apiclient_key.pem, apiclient_cert.pem) under the public/cert/wechat directory.
Unzip the certificate package for later use.
Configure the API secret key (32‑character alphanumeric string).
Backend Dependency Installation
composer require yansongda/pay ^3.0.0Configuration File
Create config/payment.php with the following structure (only essential fields shown):
<?php
return [
'wechat' => [
'default' => [
'mch_id' => '12312312321',
'mch_secret_key' => '3324324reewrwerew',
'mch_secret_cert' => public_path().'/cert/wechat/apiclient_key.pem',
'mch_public_cert_path' => public_path().'/cert/wechat/apiclient_cert.pem',
'notify_url' => 'http://webman.tinywan.com/gateway/payment/wechat-notify',
'return_url' => 'http://webman.tinywan.com/index',
// optional app IDs for various platforms
'mp_app_id' => 'dsfdsfdsfdsdfdsafds',
// ... other optional fields ...
'mode' => \Yansongda\Pay\Pay::MODE_NORMAL,
],
],
// ... unipay and logger configuration omitted for brevity ...
];Note: Place the certificate files inside the public directory of the project.
webman.tinywan.com/public$ tree -L 4
.
├── 404.html
├── cert
│ └── wechat
│ ├── apiclient_cert.p12
│ ├── apiclient_cert.pem
│ ├── apiclient_key.pem
│ └── 证书使用说明.txtUsage – Initialization
Load the configuration at runtime:
Pay::config(\config('payment'));The example uses the WeChat public account (MP) payment method.
Server‑Side Payment Code (WeChat MP)
use support\Request;
use Webman\Config;
use Yansongda\Pay\Pay;
public function recharge(Request $request): Response
{
$user['username'] = 'Tinywan';
$user['openid'] = 'fsdfsd342343241231fdsfsdafsd';
$order_sn = time();
$totalAmount = 0.01;
$discountAmount = 0;
$payAmount = $totalAmount - $discountAmount;
Pay::config(\config('payment'));
$preOrder = [
'out_trade_no' => $order_sn,
'description' => $user['username'] . ',充值开源技术小栈',
'amount' => ['total' => $payAmount * 100],
'payer' => ['openid' => $user['openid']],
];
$wechatRes = Pay::wechat()->mp($preOrder);
}Route for this endpoint: /test/recharge
Front‑End JavaScript (Layui + WeChat JS SDK)
<!-- Include Layui CSS and JS, jQuery, and WeChat JS SDK -->
<link rel="stylesheet" href="https://www.layuicdn.com/layui-v2.7.6/css/layui.css">
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
<script src="https://www.layuicdn.com/layui-v2.7.6/layui.js"></script>
<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
<script>
let paySign, appId, timeStamp, nonceStr, packageStr, signType;
layui.use(['form'], function(){
var form = layui.form, layer = layui.layer;
form.on('submit(submit)', function(data){
$.ajax({
type: "post",
dataType: "json",
data: {openId: "{$openid}", score: 100, money: 10},
url: "/test/recharge",
async: false,
success: function(data){
if(data.code === 0){
appId = data.data.appId;
paySign = data.data.paySign;
timeStamp = data.data.timeStamp;
nonceStr = data.data.nonceStr;
packageStr = data.data.package;
signType = data.data.signType;
callpay();
} else {
layer.msg("下单失败请稍后再重试", {time: 50000});
return false;
}
},
error: function(){
layer.alert('系统异常');
}
});
return false;
});
});
function callpay(){
if(typeof WeixinJSBridge == "undefined"){
if(document.addEventListener){
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
} else if(document.attachEvent){
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
}
} else {
onBridgeReady();
}
}
function onBridgeReady(){
WeixinJSBridge.invoke('getBrandWCPayRequest', {
"appId": appId,
"paySign": paySign,
"timeStamp": timeStamp,
"nonceStr": nonceStr,
"package": packageStr,
"signType": signType
}, function(res){
if(res.err_msg === "get_brand_wcpay_request:ok"){
window.location.href = 'http://webman.tinywan.com/user/home';
} else if(res.err_msg === "get_brand_wcpay_request:cancel"){
window.location.href = 'http://webman.tinywan.com/user/recharge?openid={$openid}';
} else if(res.err_msg === "get_brand_wcpay_request:fail"){
window.location.href = 'http://webman.tinywan.com/user/home?openid={$openid}';
}
});
}
</script>Asynchronous Callback (Server Side)
use support\Request;
use Webman\Config;
use Yansongda\Pay\Pay;
public function wechatNotify(Request $request): string
{
Pay::config(Config::get('payment'));
$result = Pay::wechat()->callback($request->post());
$openid = $result['resource']['ciphertext']['payer']['openid'];
$mchid = $result['resource']['ciphertext']['mchid'];
$thirdSn = $result['resource']['ciphertext']['transaction_id'];
$outTradeNo = $result['resource']['ciphertext']['out_trade_no'];
$tradeState = $result['resource']['ciphertext']['trade_state'];
$totalAmount = bcdiv((string)$result['resource']['ciphertext']['amount']['total'], '100', 2);
$success = Pay::wechat()->success()->getBody()->getContents();
return $success;
}The callback must be accessed via a POST request.
Logging
All payment‑related logs are stored in runtime/logs/pay.log within the project directory.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Open Source Tech Hub
Sharing cutting-edge internet technologies and practical AI resources.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
