微信小程序支付统一下单接口(PHP实现指南)

随着微信小程序的普及,越来越多的商家希望直接在小程序内完成支付流程,为用户提供更便捷的购物和支付体验。微信支付提供的 统一下单接口(Unified Order API),正是实现小程序支付的核心步骤。本文将结合实际 PHP 代码,为你介绍如何接入微信小程序支付。


一、为什么需要统一下单?

在小程序中,用户完成下单操作后,开发者需要调用微信支付的统一下单接口,来生成一个 预支付交易会话标识(prepay_id)

这个 prepay_id 是完成后续调起支付的关键参数,用户最终在小程序端使用它发起支付。

典型应用场景包括:

  • 电商购物支付:用户下单结算时调用微信支付;

  • 会员充值:用户购买会员或积分;

  • 虚拟商品支付:游戏道具、课程购买、增值服务;

  • 活动报名/门票支付:报名费、门票购买等。


二、接口介绍

接口地址:

POST https://api.mch.weixin.qq.com/pay/unifiedorder

必填参数:

  • appid:小程序 AppID

  • mch_id:商户号

  • nonce_str:随机字符串

  • body:商品描述

  • out_trade_no:商户订单号

  • total_fee:订单金额(单位:分)

  • spbill_create_ip:终端 IP

  • notify_url:支付结果回调通知地址

  • openid:用户标识

  • trade_type:固定为 JSAPI


三、PHP 示例代码

以下是完整的 PHP 类 WechatPay,封装了小程序支付的统一下单和支付参数生成流程:

namespace wechat;

class WechatPay {
 protected $appid;
 protected $mch_id;
 protected $key;
 protected $openid;
 protected $order_no;
 protected $amount;

 function __construct($openid, $order_no, $amount) {
 $config = config('wechat');
 $this->appid = $config['app_id'];
 $this->openid = $openid;
 $this->mch_id = $config['mch_id'];
 $this->key = $config['key'];
 $this->order_no = $order_no;
 $this->amount = $amount;
 }

 public function pay($body, $notify) {
 // 调用统一下单接口
 return $this->weixinapp($body, $notify);
 }

 // 调用统一下单
 private function unifiedorder($body, $notify) {
 $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
 $parameters = [
 'appid' => $this->appid,
 'mch_id' => $this->mch_id,
 'nonce_str' => $this->createNoncestr(),
 'body' => $body,
 'out_trade_no' => $this->order_no,
 'total_fee' => $this->amount,
 'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],
 'notify_url' => $notify,
 'openid' => $this->openid,
 'trade_type' => 'JSAPI'
 ];
 $parameters['sign'] = $this->getSign($parameters);
 $xmlData = $this->arrayToXml($parameters);
 return $this->xmltoarray($this->postXmlSSLCurl($xmlData, $url));
 }

 // 小程序调起支付参数
 private function weixinapp($body, $notify) {
 $unifiedorder = $this->unifiedorder($body, $notify);
 if ($unifiedorder['return_code'] == 'FAIL') {
 return $unifiedorder;
 }
 $parameters = [
 'appId' => $this->appid,
 'timeStamp' => ''.time().'',
 'nonceStr' => $this->createNoncestr(),
 'package' => 'prepay_id='.$unifiedorder['prepay_id'],
 'signType' => 'MD5'
 ];
 $parameters['paySign'] = $this->getSign($parameters);
 return $parameters;
 }

 // 生成随机字符串
 private function createNoncestr($length = 32) {
 $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
 $str = "";
 for ($i = 0; $i < $length; $i++) {
 $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
 }
 return $str;
 }

 // 生成签名
 private function getSign($Obj) {
 ksort($Obj);
 $String = $this->formatBizQueryParaMap($Obj, false);
 $String = $String."&key=".$this->key;
 return strtoupper(md5($String));
 }

 private function formatBizQueryParaMap($paraMap, $urlencode) {
 $buff = "";
 ksort($paraMap);
 foreach ($paraMap as $k => $v) {
 if ($urlencode) $v = urlencode($v);
 $buff .= $k . "=" . $v . "&";
 }
 return rtrim($buff, "&");
 }

 // 数组转XML
 public function arrayToXml($arr) {
 $xml = "<root>";
 foreach ($arr as $key => $val) {
 $xml .= is_array($val) 
 ? "<{$key}>".$this->arrayToXml($val)."</{$key}>" 
 : "<{$key}>{$val}</{$key}>";
 }
 $xml .= "</root>";
 return $xml;
 }

 // XML转数组
 public function xmltoarray($data) {
 $obj = simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA);
 return json_decode(json_encode($obj), true);
 }

 // 发送请求
 public function postXmlSSLCurl($data, $url) {
 $curl = curl_init();
 curl_setopt($curl, CURLOPT_URL, $url);
 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
 if (!empty($data)) {
 curl_setopt($curl, CURLOPT_POST, 1);
 curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
 }
 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
 $output = curl_exec($curl);
 curl_close($curl);
 return $output;
 }
}

$config = config('wechat');

四、注意事项

  1. 签名机制:必须严格按照微信支付规则拼接字符串并附加 key

  2. 金额单位total_fee 单位是 ,例如 100 代表 1 元;

  3. 商户订单号out_trade_no 必须唯一,防止重复下单;

  4. 回调地址notify_url 必须是公网可访问的 HTTPS 地址;

  5. 前端调起支付:后端返回的 appIdtimeStampnonceStrpackagesignTypepaySign,小程序前端使用 wx.requestPayment 接口完成支付。


五、应用场景举例

  • 电商小程序:用户下单购买商品;

  • 会员充值:购买 VIP、积分、课程;

  • O2O 服务:预约家政、出行服务支付;

  • 活动报名:门票支付、报名费支付。


六、总结

微信小程序支付的核心就是 统一下单。后端通过调用该接口获取 prepay_id,前端再调起支付接口完成交易。

通过封装好的 PHP 类 WechatPay,商家可以快速接入微信支付,实现安全、便捷的小程序支付功能,提升用户体验。


点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿
发表
评论
返回
顶部