第一次写,主要给自己看,记录一下
利用微信开发者工具开发商城类微信小程序,开发微信支付必不可少,但微信支付api开发文档说明压根看不懂,自己摸索,运行报错找不到错误代码解决方法
先说说我的开发流程吧
小程序前端——小程序js网络请求php后台——后台接收小程序传回数据——微信支付官网下载sdk包——微信商户配置——sdk配置——签名验证获取prepay_id——传回前端调用微信支付api——完成
想要完成微信支付就必须获取由微信系统后台传回的prepay_id,就必须要生成正确的签名
微信官方文档说明
-
微信官方文档说明https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
-
支付SDKhttps://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
做好一切准备,前端后端配置要求都编写完毕,编译运行,签名错误,检查一遍,更改商户号,商户key,编译运行,签名错误,网上百度查各种方法总结一下
- 查看小程序appid,商户号,商户key,小程序密钥是否正确匹配
- 检查签名拼接是否按要求拼接,用签名验证工具验证一下https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=20_1
- 修改商户key,原封不动的改一次 key设置路径:微信商户平台(pay.weixin.qq.com)–>账户设置–>API安全–>密钥设置
- 检查商户是否对支付目录授权,必须授权才可以,然后商户对appid授权会生成一个商户号对应
我就是败在了第4点上,检查了一遍又一遍发现没有授权目录与appid,因为商户号是可变动的,一定要与appid匹配我就是败在了第4点上,检查了一遍又一遍发现没有授权目录与appid,因为商户号是可变动的,一定要与appid匹配
签名算法
<?php
/*
* 小程序微信支付
*/
class WeixinPay {
protected $appid;
protected $mch_id;
protected $key;
protected $openid;
protected $out_trade_no;
protected $body;
protected $total_fee;
function __construct($appid, $openid, $mch_id, $key,$out_trade_no,$body,$total_fee) {
$this->appid = $appid;
$this->openid = $openid;
$this->mch_id = $mch_id;
$this->key = $key;
$this->out_trade_no = $out_trade_no;
$this->body = $body;
$this->total_fee = $total_fee;
}
public function pay() {
//统一下单接口
$return = $this->weixinapp();
return $return;
}
//统一下单接口
private function unifiedorder() {
$url = \'https://api.mch.weixin.qq.com/pay/unifiedorder\';
$jjc=$this->createNoncestr();
$parameters = array(
\'appid\' => $this->appid,
\'body\' => $this->body,
\'mch_id\' => $this->mch_id,
\'nonce_str\' => $jjc,
\'notify_url\' => \'https://*************/notify.php\',
\'openid\' => $this->openid,
\'out_trade_no\'=> $this->out_trade_no,
\'spbill_create_ip\' => \'*********\',//授权目录的ip地址
\'total_fee\' => $this->total_fee,
\'trade_type\' => \'JSAPI\'
);
$t=\"appid=\".$this->appid.\"&body=\".$this->body.\"&mch_id=\".$this->mch_id.\"&nonce_str=\".$jjc.\"¬ify_url=https://*************/notify.php&openid=\".$this->openid.\"&out_trade_no=\".$this->out_trade_no.\"&spbill_create_ip=************&total_fee=\".$this->total_fee.\"&trade_type=JSAPI\";
$t=$t.\"&key=************************************\";
$sign=strtoupper(md5($t));
$parameters[\'sign\']=$sign;
$xmlData = $this->arrayToXml($parameters);
$return = $this->xmlToArray($this->postXmlCurl($xmlData, $url, 60));
return $return;
}
private static function postXmlCurl($xml, $url, $second = 30)
{
$ch = curl_init();
//设置超时
curl_setopt($ch, CURLOPT_TIMEOUT, $second);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); //严格校验
//设置header
curl_setopt($ch, CURLOPT_HEADER, FALSE);
//要求结果为字符串且输出到屏幕上
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
//post提交方式
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);
curl_setopt($ch, CURLOPT_TIMEOUT, 40);
set_time_limit(0);
//运行curl
$data = curl_exec($ch);
//返回结果
if ($data) {
curl_close($ch);
return $data;
} else {
$error = curl_errno($ch);
curl_close($ch);
throw new WxPayException(\"curl出错,错误码:$error\");
}
}
//数组转换成xml
private function arrayToXml($arr) {
$xml = \"<root>\";
foreach ($arr as $key => $val) {
if (is_array($val)) {
$xml .= \"<\" . $key . \">\" . arrayToXml($val) . \"</\" . $key . \">\";
} else {
$xml .= \"<\" . $key . \">\" . $val . \"</\" . $key . \">\";
}
}
$xml .= \"</root>\";
return $xml;
}
//xml转换成数组
private function xmlToArray($xml) {
//禁止引用外部xml实体
libxml_disable_entity_loader(true);
$xmlstring = simplexml_load_string($xml, \'SimpleXMLElement\', LIBXML_NOCDATA);
$val = json_decode(json_encode($xmlstring), true);
return $val;
}
//微信小程序接口
private function weixinapp() {
//统一下单接口
$unifiedorder = $this->unifiedorder();
// print_r($unifiedorder);
$jjc=$this->createNoncestr();
$parameters = array(
\'appId\' => $this->appid, //小程序ID
\'nonceStr\' => $jjc, //随机串
\'package\' => \'prepay_id=\' . $unifiedorder[\'prepay_id\'], //数据包
\'signType\' => \'MD5\',//签名方式
\'timeStamp\' => \'\' . time() . \'\' //时间戳
);
//签名
$t=\"appId=\".$this->appid.\"&nonceStr=\".$jjc.\"&package=prepay_id=\".$unifiedorder[\'prepay_id\'].\"&signType=MD5&timeStamp=\".time();
$t=$t.\"&key=*************************\";
$sign=strtoupper(md5($t));
$parameters[\'paySign\'] = $sign;
return $parameters;
}
//作用:产生随机字符串,不长于32位
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) {
foreach ($Obj as $k => $v) {
$Parameters[$k] = $v;
}
//签名步骤一:按字典序排序参数
ksort($Parameters);
$String = $this->formatBizQueryParaMap($Parameters, false);
//签名步骤二:在string后加入KEY
$String = $String . \"&key=\" . $this->key;
//签名步骤三:MD5加密
$String = md5($String);
//签名步骤四:所有字符转为大写
$result_ = strtoupper($String);
return $result_;
}
///作用:格式化参数,签名过程需要使用
private function formatBizQueryParaMap($paraMap, $urlencode) {
$buff = \"\";
ksort($paraMap);
foreach ($paraMap as $k => $v) {
if ($urlencode) {
$v = urlencode($v);
}
$buff .= $k . \"=\" . $v . \"&\";
}
$reqPar;
if (strlen($buff) > 0) {
$reqPar = substr($buff, 0, strlen($buff) - 1);
}
return $reqPar;
}
}
以上就是我微信支付解决的过程,没有太大的坑,但是记录一下,免的以后自己再次遇到
版权声明
本文仅代表作者观点,不代表百度立场。
本文系作者授权百度百家发表,未经许可,不得转载。




