In an earlier article on this site, I introduced a method for receiving and handling WeChat Pay notification messages in WordPress. That method can process the notification directly, determine the payment status, and then handle the order accordingly, but it cannot send the notification result back to the front end and tell the user about the payment status in the browser. That is not very user-friendly.
Improve the user experience by actively querying the WeChat order payment status
While displaying the QR code, we can add a piece of JavaScript that periodically queries the order payment status with Ajax, and then use the payment status returned by the server to notify the user on the front end. This gives the payment flow a much better user experience. Below is the front-end JavaScript implementation.
// Submit the order through Ajax, which will return JSON containing the QR code image and order number
$("#form-checkout").submit(function () {
event.preventDefault();
var address_id = $('input[name="address_id"]:checked').val();
$.ajax({
url : '<?= home_url( 'orders/add' ); ?>',
type : 'POST',
dataType: 'json',
data : {
'address_id': address_id,
},
success : function (data) {
$("#qrcode").html('<img src="' + data.url + '">');
window.view.query(data.out_trade_no);
},
error : function (errorThrown) {
console.log(errorThrown);
}
});
return false;
});
// Periodically query the WeChat Pay status endpoint, and redirect if successful
window.view = {
query: function (out_trade_no) {
$.ajax({
type : "POST",
url : '<?php echo home_url( 'query-tid' ); ?>',
data : {
out_trade_no: out_trade_no
},
timeout : 6000,
cache : false,
dataType: 'json',
success : function (data) {
if (data && data.errcode == 0) {
location.href = data.errmsg;
return;
}
setTimeout(function () {
window.view.query(out_trade_no);
}, 2000);
},
error : function () {
setTimeout(function () {
window.view.query(out_trade_no);
}, 2000);
}
});
}
};
Back-end implementation for querying the WeChat Pay interface
Here I use WordPress Dispatcher and Omnipay to simplify the implementation of the query endpoint. With just a few lines of code, we can build the required WeChat payment query flow. The key point to note here is that whether the payment succeeded is determined by the trade_state field returned by the WeChat Pay interface.
/**
* Query a WeChat Pay order
*/
new Dispatch( [
// Add subscription
'query-tid' => function ( $request ) {
$out_trade_no = $_POST[ 'out_trade_no' ];
$order_post_id = $_POST[ 'order_post_id' ];
$gateway = get_wechat_gateway();
// Query the WeChat Pay order
$response = $gateway->query( [
'out_trade_no' => $out_trade_no,
] )->send();
// If the transaction state is success, return the success message
if ( $response->getData()[ 'trade_state' ] === 'SUCCESS' ) {
$data = [
'errcode' => 0,
'errmsg' => get_permalink( $order_post_id ),
];
wp_send_json( $data );
}
},
] );
With the payment handling logic above in place, the WeChat Pay flow becomes noticeably friendlier. The site feels more professional and more trustworthy because the user is redirected to a clear internal success page as soon as the payment is confirmed. Besides the approach above, we could also notify the user through sockets after a successful WeChat payment, but that method is more complex. I have not had a chance to try it yet, and if I do later, I will write another article about it.
