条件:申请微信支付商户号,拥有
商户号id及商户号密钥
一、微信接口
https://developers.weixin.qq.com/miniprogram/dev/api/open-api/payment/wx.requestPayment.html#wxrequestpaymentobject
这几个参数需要通过wx.request从后台得到
前台代码:
wx.request({
url: '后台地址',
data: {
//根据需要所传参数
},
method: 'POST',
header: {
'content-type': 'application/x-www-form-urlencoded'
},
success: function (response) {
// console.log(response.data);
// 发起支付 出现支付页面
wx.requestPayment({
'timeStamp': response.data.timeStamp,
'nonceStr': response.data.nonceStr,
'package': response.data.package,
'signType': 'MD5',
'paySign': response.data.paySign,
success: function (res) {
wx.showToast({
title: '支付成功'
});
// 跳转页面
wx.switchTab({
url: '../index'
})
},
fail:function(res){
console.log(res);
}
});
}
});
二、后台代码(PHP)
一大部分与公众号是一样的,可以看这个人的视频来学习
https://www.imooc.com/u/197650/courses?sort=publish
代码里的很多算法原理讲的很清楚
上代码!
(代码我也是学习的,原链接在这里
https://segmentfault.com/a/1190000014444847)
<?php
date_default_timezone_set("PRC");
class PayController{
private $appid=""; //小程序appid
private $appsecret= ""; //小程序的secret
private $MCHID=""; //商户号id
private $KEY=""; //商户号key
/*
* 发起支付回调支付信息
* by:leoyi
* Date:2018-4-8
*/
public function payOrder($total,$r_openid,$r_body,$r_trade_no){
$total_fee = $total; //支付金额
//$total_fee = 1;
$openid = $r_openid; //用户的Openid
if(empty($total_fee) || empty($openid)){ //一定要有用户Openid和支付金额
die("缺少参数!");
}
$appid = $this->appid;
$MCHID = $this->MCHID; //商户号
$KEY = $this->KEY; //商户key
$url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
$data['appid'] = $appid; //小程序appid
$data['mch_id'] = $MCHID; //商户号id
$data['nonce_str'] = md5($MCHID.time()); //验证的支付
$data['openid'] = $openid; //用户openid
$data['body'] = $r_body; //微信支付对应的商家/公司主体名
$data['out_trade_no'] = $r_trade_no; //订单号id,用于回调改订单状态
$data['total_fee'] = $total_fee; //支付金额,单位为分!!
$data['spbill_create_ip'] = '8.8.8.8'; //验证ip地址,这个不用改随意
$data['notify_url'] = "";
//微信支付成功的回调路径,必须是外网可以访问的链接,必须在支付文件的同目录下
//不能带参数
//这是个巨大的坑,到现在也没懂,所以回调采用了别的方法,下面介绍
$data['trade_type'] = "JSAPI"; //小程序支付,所以是JSAPI
// --------------------以下这一串都不用改--------------------------------
ksort($data);
$sign_str = $this->ToUrlParams($data);
$sign_str = $sign_str."&key=".$KEY;
$data['sign'] = strtoupper(md5($sign_str));
$xml = $this->arrayToXml($data);
$r = $this->postXmlCurl($xml,$url,true);
$result = json_decode($this->xml_to_json($r));
//var_dump($result);
if($result->return_code == 'SUCCESS'){
$stringtime = date("Y-m-d H:i:s",time());
$sdata['timeStamp'] = (string)strtotime($stringtime); //必须为字符串类型
$sdata['appId'] = $appid;
// $sdata['timeStamp'] = time();
$sdata['nonceStr'] = md5(time().rand().rand().$openid);
if(isset($result->prepay_id)) {
$sdata['package'] = "prepay_id=" . $result->prepay_id; //必须带前面的prepay_id
}
$sdata['signType'] = "MD5";
ksort($sdata);
$sign_str = $this->ToUrlParams($sdata);
$sign_str = $sign_str."&key=".$KEY;
$sdata['paySign'] = strtoupper(md5($sign_str));
echo json_encode($sdata);
}
else{
echo "失败";
}
// -----------------------都不用改-----------------------------------------------
//这些方法如果不懂在上面的视频链接中都能找到讲解,这与公众号是一模一样的
public function postXmlCurl($xml, $url, $useCert = false, $second = 10)
{
$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);//严格校验2
//设置header
curl_setopt($ch, CURLOPT_HEADER, FALSE);
//要求结果为字符串且输出到屏幕上
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
//运行curl
$data = curl_exec($ch);
//返回结果
if($data){
curl_close($ch);
return $data;
} else {
$error = curl_errno($ch);
curl_close($ch);
return $error;
}
}
public function ToUrlParams($data)
{
$buff = "";
foreach ($data as $k => $v)
{
if($k != "sign" && $v != "" && !is_array($v)){
$buff .= $k . "=" . $v . "&";
}
}
$buff = trim($buff, "&");
return $buff;
}
public 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;
}
public function xml_to_json($xmlstring) {
return json_encode($this->xml_to_array($xmlstring),JSON_UNESCAPED_UNICODE);
}
public function post_url($post_data, $url)
{
$ch = curl_init();
//设置超时
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);//严格校验2
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
public function xml_to_array($xml) {
//return ((array) simplexml_load_string($xmlstring));
return simplexml_load_string($xml,'SimpleXMLElement',LIBXML_NOCDATA);
//return json_decode(xml_to_json($xmlstring));
}
}
//整个类写完记得要实例化
$total_fee = $_POST['totalFee']; //支付金额
$openid = $_POST['openid'];
$body = $_POST['body']; //商家名
$trade_no = $_POST['tradeNo']; //订单编号
$demo = new PayController();
$demo->payOrder($total_fee,$openid,$body,$trade_no);
三、支付成功后修改订单状态
在支付的后端代码里是有回调路径的,但是这个…反正我没搞明白,如果我搞明白了我再来补这个坑。
所以采用了另外的方法:在wx.requestPayment成功后再对后端进行请求再更改状态
就更容易理解了,注意局部变量的使用,保证参数有效。