最近做了一个小程序支付,发现网上还是有很多问题的今天就把整个思路和代码贴给大家并详细的讲解一下
思路:
1.预支付
2.预支付返回的prepay_id 进行重新组建数据,搭建需要的参数调用js进行移动端支付
3.在2步骤中上传的notify_url地址就是回调地址记住:小程序这个地址不允许有参数切记,在这个地址中处理你的服务器的逻辑
准备的数据:
1.小程序appid
2.小程序绑定的商户号
3.商户号申请或者重置后的key值
代码:
1.准备配置公共配置参数
static $wxpayconf = [
'wx_smallprogram_appid'=>'wx13212312313123',// 小程序appid
'mch_id'=>12312345454 ,// 小程序商户号
'key'=>'Gjanuarygaoqingsong',
'appsecret'=>'1231231212daseqe123213',
'notify_url'=>'http://www.gaoqingsong.com/index.php?',// 支付回调地址
];
2.预支付部分(其实就是统一下单和微信公众号的都一样不过这里我还要贴出来), 支付环境配置部分:
// 统一下单,并且直接支付
public function unifiedorder($paydata,$orderSn){
// 初始化小程序支付配置
$wxpayconf = self::$wxpayconf;
$userIP = $_SERVER['REMOTE_ADDR'];
$sign['appid'] = $appid = $wxpayconf['wx_smallprogram_appid'];
$sign['mch_id'] = $mch_id = $wxpayconf['mch_id'];
$sign['nonce_str'] = $nonce_str = $this->nonceStr();
$sign['body'] = $body = 'Gjanury测试商品';
$sign['out_trade_no'] = $out_trade_no = $orderSn;
$sign['total_fee'] = $total_fee = 1/*$paydata['actualpayment'] * 100*/;// 单位是分 1元 = 100分
$sign['spbill_create_ip'] = $spbill_create_ip = $userIP;// 终端客户端ip
$sign['trade_type'] = $trade_type = 'JSAPI';
$sign['openid'] = $openid = $paydata['openid'];
$sign['notify_url'] = $notify_url = $wxpayconf['notify_url'];;
$sign['sign'] = $this->getSign($sign,$wxpayconf['key']);
// 统一下单接口
$url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
$data = $this->arrayToXml($sign);
$res = $this->postXmlCurl($data,$url);
if($res['errNum'] != 0){
echo json_encode($res);
die;
}else{
$res = $res['info'];
}
if($res['return_code'] == 'SUCCESS' && $res['result_code'] == 'SUCCESS'){
$prepay_id = $res['prepay_id'];
// prepay_id的为预支付
// 小程序提供的是接口而已。直接调出即可
// 支付环境参数配置部分
$yuzhifudata['appId'] = $wxpayconf['wx_smallprogram_appid'];
$yuzhifudata['package'] = 'prepay_id='.$prepay_id;
$yuzhifudata['timeStamp'] = (string)time();
$yuzhifudata['nonceStr'] = $this->nonceStr();
$yuzhifudata['signType'] = 'MD5';
$yuzhifudata['paySign'] = $this->getSign($yuzhifudata,$wxpayconf['key']);
exit(json_encode($yuzhifudata));
}else{
if($res['return_code'] == 'FAIL'){
$info['return_msg'] = $res['return_msg'];
}
if($res['result_code'] == 'FAIL'){
$info['err_code'] = $res['err_code'];
$info['err_code_des'] = $res['err_code_des'];
}
exit($info);
}
// 签名方法
private function getSign($params, $key1)
{
//签名步骤一:按字典序排序数组参数
ksort($params);
$singstring = '';
foreach ($params as $key => $value) {
$singstring .= '&'.$key . '=' . $value;
}
$string = $singstring . "&key=" . $key1;
//签名步骤三:MD5加密
$string = ltrim($string,'&');
$string = md5($string);
//签名步骤四:所有字符转为大写
$result = strtoupper($string);
return $result;
}
// 数组转xml
public function arrayToXml($arr,$is_array=false){
if (!$is_array){
$xml = '<xml>';
}
foreach ($arr as $key=>$val){
if(is_array($val)){
$xml.="<".$key.">".$this->arrayToXml($val,true)."</".$key.">";
}else{
$xml.="<".$key.">".$val."</".$key.">";
}
}
if (!$is_array){
$xml.="</xml>";
}
return $xml;
}
3.小程序js部分:
wx.request({
url: 'http://www.gaoqingsong.com/index.php?m=xxxx&a=payment',
data: {
tablenumber: tablenumber,// 下单桌号
orderdetail: JSON.stringify(that.data.goods),// 点餐的详情,对象转化成json字符串方便后台进行存储调用
amount: that.data.totalprice,// 订餐的总价格
actualpayment: that.data.totalprice,// 实际付款金额
openid: useropenid,// 实际付款金额
wxheadimg: wxinfo.avatarUrl,
wxname: wxinfo.nickName,
},
method: "POST",
header: {
"content-type": "application/x-www-form-urlencoded"// post方式提交用这种header头
},
success: function (res) {
wx.navigateTo({
url: '../paysuccess/paysuccess'
});
var timeStamp = res.data.timeStamp;
wx.requestPayment(
{
'timeStamp': timeStamp,
'nonceStr': res.data.nonceStr,
'package': res.data.package,
'signType': res.data.signType,
'paySign': res.data.paySign,
'success': function (res) {
if(res.errMsg == 'requestPayment:ok'){
wx.navigateTo({
url: '../paysuccess/paysuccess'
});
}
},
'fail': function (res) {
console.log(res);
},
'complete': function (res) { }
}
)
}
})
4.回调页面代码:
$receipt = $_REQUEST;
if($receipt==null){
$receipt = file_get_contents("php://input");
}
if($receipt == null){
$receipt = $GLOBALS['HTTP_RAW_POST_DATA'];
}
$post_data = $this->xml_to_array($receipt);
$postSign = $post_data['sign'];
unset($post_data['sign']);
ksort($post_data);// 对数据进行排序
$str = $this->ToUrlParams($post_data);//对数组数据拼接成key=value字符串
$user_sign = strtoupper(md5($post_data)); //再次生成签名,与$postSign比较
$ordernumber = $post_data['out_trade_no'];// 订单可以查看一下数据库是否有这个订单
if($post_data['return_code']=='SUCCESS'&&$postSign){
// 查询订单是否已经支付
$result = M('userorder')->where('ordernumber = "'.$ordernumber.'"')->select();
if($result){
if($result[0]['paystatus'] == 0){
// 进行更改支付成功状态
$obj = array(
"paystatus" =>1,
);
$res = M('userorder')->where('ordernumber = "'.$ordernumber.'"')->save($obj);
file_put_contents('gg.txt',$res);
if($res){
$this->return_success();
}
}else{
$this->return_success();
}
}else{
echo '微信支付失败,数据未存在该订单。';
}
}else{
// 写个日志记录
file_put_contents('wxpayerrorlog.txt',$post_data['return_code'].PHP_EOL, FILE_APPEND);
echo '微信支付失败';
}
5.效果图:
1.web开发端效果:
2.移动端效果:
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/39325.html