资讯专栏INFORMATION COLUMN

微信小程序支付全问题解决

Tecode / 1054人阅读

摘要:这几天在做小程序的支付,没有用官方的,这里就纯用官方的文档搞一发。

这几天在做小程序的支付,没有用官方的SDK,这里就纯用官方的文档搞一发。

* 注作者使用的PHP,不过支付流程都是这样

开发前必读 主要流程

小程序前端发送求参请求

接受请求封装 “统一下单” 获取package

小程序接受 “统一下单” 获取的package值带入wx.requestPayment发起支付请求

准备工具

申请小程序微信支付

拿到小程序微信支付的商户号及设置秘钥

注意:小程序就只需要这两步,如果是web的话还需要设置支付目录授权域名,文档里面也有写的:https://pay.weixin.qq.com/wik...


统一下单
官方文档:https://pay.weixin.qq.com/wik...
/**
 * 统一订单
 */
public function unifiedorder(){
    // 以下配置是必填项,如有其它需求请自行配置
    $config = array(
        "appid"         =>    "xxxxxxx",//这里是小程序appid
        "mch_id"        =>    "xxxxxxx",//商户ID
        "nonce_str"     =>    $this->getNonceStr(),//随机字符串
        "body"          =>    "这里是测试 - 测试",//请按照文档要求填写合格名称
        "out_trade_no"  =>    time().$this->getNonceStr(2),//流水单号
        "total_fee"     =>    "20",//金额,分为单位,这里是0.2元
        "spbill_create_ip" => "123.123.123.123",//当前IP
        "notify_url"    =>    "http://xxxx.com",//请恕我愚昧,我没搞懂他有什么用
        "trade_type"    =>    "JSAPI",//必须填写JSAPI
        "openid"        =>    "xxxxxxxx"//当前用户的openid,在trade_type=JSAPI的时候,此项就变成必填项了
    );
    $config["sign"] = $this->getSignPay($config);
    $xmlData = $this->ToXml($config);//转成xml数据
    $postData = $this->http_post($xmlData);
    $arrayData = $this->FromXml($postData);
    if($arrayData["return_code"] == "SUCCESS" || $arrayData["result_code"] == "SUCCESS"){
        return $arrayData["prepay_id"];//重点来了:走了这么多路,就为了这个值。到这一步就证明成功一多半了。
    }else{
        return $arrayData;//返回错误
    }
}

/**
 * 获取签名
 */
public function getSignPay($config){
    $key = "xxxxxxx";//商户秘钥,就是自己生成的32位密码
    $strA = "appid=".$config["appid"]."&body=".$config["body"]."&mch_id=".$config["mch_id"]."&nonce_str=".$config["nonce_str"]."¬ify_url=".$config["notify_url"]."&spbill_create_ip".$config["spbill_create_ip"]."&total_fee=".$config["total_fee"]."&trade_type=".$config["trade_type"];//ASCII 字典序
    $strB = $strA."&key=".$key;
    $sign = strtoupper(md5($strB));//大写MD5
    return $sign;
}

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

/**
 * array转XML
 */
public function ToXml($data){
    if(!is_array($data) || count($data) <= 0){
        throw new WxPayException("数组数据异常!");
    }
    $xml = "";
    foreach ($data as $key=>$val){
        $xml.="<".$key.">".$val."";
    }
    $xml.="";
    return $xml; 
}

/**
 * xml转array
 */
public function FromXml($xml){    
    if(!$xml){
        throw new WxPayException("xml数据异常!");
    }
    libxml_disable_entity_loader(true);
    $this->values = json_decode(json_encode(simplexml_load_string($xml, "SimpleXMLElement", LIBXML_NOCDATA)), true);
    return $this->values;
}


/**
 * post 请求
 */
public function http_post($url,$param,$post_file=false){
    $oCurl = curl_init();
    if(stripos($url,"https://")!==FALSE){
        curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
    }
    if (PHP_VERSION_ID >= 50500 && class_exists("CURLFile")) {
        $is_curlFile = true;
    } else {
        $is_curlFile = false;
        if (defined("CURLOPT_SAFE_UPLOAD")) {
            curl_setopt($oCurl, CURLOPT_SAFE_UPLOAD, false);
        }
    }
    if (is_string($param)) {
        $strPOST = $param;
    }elseif($post_file) {
        if($is_curlFile) {
            foreach ($param as $key => $val) {
                if (substr($val, 0, 1) == "@") {

                }
            }
        }
        $strPOST = $param;
    } else {
        $aPOST = array();
        foreach($param as $key=>$val){
            $aPOST[] = $key."=".urlencode($val);
        }
        $strPOST =  join("&", $aPOST);
    }
    curl_setopt($oCurl, CURLOPT_URL, $url);
    curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );
    curl_setopt($oCurl, CURLOPT_POST,true);
    curl_setopt($oCurl, CURLOPT_POSTFIELDS,$strPOST);
    $sContent = curl_exec($oCurl);
    $aStatus = curl_getinfo($oCurl);
    curl_close($oCurl);
    if(intval($aStatus["http_code"])==200){
        return $sContent;
    }else{
        return false;
    }
}

好了现在已经获取到了 prepay_id 的值,我们的统一下单就算完成了,其实我更乐意叫他数据封装


小程序微信支付
官方文档:https://developers.weixin.qq....

先来一个插曲,首先我们小程序的前端需要去触发pay,实现的功能肯定是要点击小程序的一个触发,然后才能支付对吧,

pay:function(e){
    //这里面使用post去请求。然后通过我接下来要写的API支付代码获取小程序支付参数
    success:function(res){
         wx.requestPayment({
             "timeStamp":toString(res.timeStamp),//这里转字符串,这里被坑过,不转的话可能会出现total_fee为空
             "nonceStr":toString(res.nonceStr),
             "package":toString(res.package),
             "signType":"MD5",
             "paySign":toString(res.paySign),
             success:function(res){
                 console.log(res);//这里可以跳转到带参地址
             },
             fail:function(res){
                 console.info("支付失败",res);
             },
             complete:function(){
                 console.info("支付触发回调",res);
             }
         })  
    }
       
}
api支付

也就是上面小程序代码的后端请求地址

/**
 * api组装数据
 */
public function payApiBlack(){
    $appid = "xxxxxx";//小程序appid,上面有重复,不过这样比较直观
    $timeStamp = time();
    $nonceStr = $this->getNonceStr();//这是调用统一下单里面的方法,为了直观,我把这些代码都写在了一个类里
    $package = "prepay_id=".$this->unifiedorder();
    $signType = "MD5";
    $key = "xxxxxx";//这里是商户秘钥,32位,同上面也有
    $strA = "appId=".$appid."&nonceStr=".$nonceStr."package=".$package."&= signType=".$signType."&timeStamp=".$timeStamp."&key=".$key;
    $paySign = strtoupper(md5($strA));
    $data = array(
        "appid"=>$appid,
        "timeStamp"=>$timeStamp,
        "nonceStr"=>$nonceStr,
        "package"=>$package,
        "signType"=>$signType
    );
    return $data;//返回给小程序
}

以上就是全部代码,还有小程序的支付回调没有什么信息,所以,我的思路判断success后进行跳转带参

//此代码为wx.requestPayment success,部分代码省略
//res 回调参数包括用户uid及其他重要传递
success:function(res){
    wx.redirect({
        url:"pages/pay/done?uid="+res.uid
    })
}

当然那个统一下单的 notify_url 好像与回调有关,至于怎么用,试了几次回调的CURD都没反应,所以有空再研究啦。

以上代码仅作为支付流程解释,所以真正要用到项目上,还是去套官方的SDK吧,毕竟涉及到钱嘛

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/29155.html

相关文章

  • 行业log | 小程序搭载智慧零售,实现五位一体数字化营销

    摘要:零售商家通过微信支付小程序实现线上线下消费一体化,通过线上支付线下单品完成商品数据的打通。因此小程序搭载智慧零售,能助力商家实现消费场景数字化以及购买行为具象化,从新的维度提高用户服务水平。 随着移动互联网、大数据、AI等技术日益成熟,实体行业领域的转型成为业绩提升的关键。对于零售行业从业者,这意味着思维方式的自我进化,对于消费者,则意味着与产品产生新的连接,享受更加个性化、更具人情味...

    mzlogin 评论0 收藏0
  • 行业log | 小程序搭载智慧零售,实现五位一体数字化营销

    摘要:零售商家通过微信支付小程序实现线上线下消费一体化,通过线上支付线下单品完成商品数据的打通。因此小程序搭载智慧零售,能助力商家实现消费场景数字化以及购买行为具象化,从新的维度提高用户服务水平。 随着移动互联网、大数据、AI等技术日益成熟,实体行业领域的转型成为业绩提升的关键。对于零售行业从业者,这意味着思维方式的自我进化,对于消费者,则意味着与产品产生新的连接,享受更加个性化、更具人情味...

    mdluo 评论0 收藏0
  • 行业log | 小程序搭载智慧零售,实现五位一体数字化营销

    摘要:零售商家通过微信支付小程序实现线上线下消费一体化,通过线上支付线下单品完成商品数据的打通。因此小程序搭载智慧零售,能助力商家实现消费场景数字化以及购买行为具象化,从新的维度提高用户服务水平。 随着移动互联网、大数据、AI等技术日益成熟,实体行业领域的转型成为业绩提升的关键。对于零售行业从业者,这意味着思维方式的自我进化,对于消费者,则意味着与产品产生新的连接,享受更加个性化、更具人情味...

    rottengeek 评论0 收藏0
  • Antmove 缘起 - 好用的小程序多端解决方案

    摘要:目前支持哪些平台的搬家目前对外开放版本释放了微信小程序转支付宝小程序的功能,这也是我们在调研中发现需求最多的。从笔者的了解来看,微信小程序框架原理更接近于,而支付宝小程序更接近于。 原文地址: https://ant-move.github.io/we... 蚂蚁搬家工具(Antmove)是一个小程序开发辅助工具,致力于解决小程序跨平台开发的难题,借助于 Antmove,你只需要编写...

    crelaber 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<