小程序微信支付 - CSDN
精华内容
参与话题
  • 直接把里面的参数替换成你的就可以了,前提是你要开通的有微信支付功能,需要商户号,appid,appsecret,openid, openid的获取比较简单,我再写一篇博客做介绍,不懂得可以私聊我 //小程序端代码: pay:...

    这里我直接上代码,附有注释,直接把我的代码粘贴一下就可以用了,也是自己走了好多的弯路。。,写在博客里做个记录

    直接把里面的参数替换成你的就可以了,前提是你要开通的有微信支付功能,需要商户号,appid,appsecret,openid,

    openid的获取比较简单,我再写一篇博客做介绍,不懂得可以私聊我

    //小程序端代码:

     

    pay:function(){

    var that=this

    wx.getStorage({

    key: 'openid',

    success: function(res) {

    wx.request({

    //这里是后台的处理方法,url是自定义的,直接换成你自己的后台处理方法即可,Wx_Pay这个方法在下面写的有
    //后台用的php做处理,java的可以参考方法,道理都是一样的

    url: url + 'Wx_Pay',

    data: {
    //用户的openid
    openid:res.data,

    fee: that.data.totalPrice, //支付金额

    details: that.data.goodsList[0].goods_name,//支付商品的名称

    },

    success:function(result){

    if(result.data){

    //out_trade_no=res.data['out_trade_no'];

    wx.requestPayment({

    timeStamp: result.data['timeStamp'],

    nonceStr: result.data['nonceStr'],

    package: result.data['package'],

    signType: 'MD5',

    paySign: result.data['paySign'],

    'success':function(successret){

    console.log('支付成功');
    //获取支付用户的信息

    wx.getStorage({

    key: 'userInfo',

    success: function (getuser) {
    //加入订单表做记录

    wx.request({

    url: url + 'Wx_AddOrder',

    data: {

    uname: getuser.data.nickName,

    goods: that.data.goodsList[0].goods_name,

    price: that.data.totalPrice,

    openid:res.data,

    },

    success: function (lastreturn) {

    console.log("存取成功");

    }

    })

    },

    })

    },'fail':function(res){

    }

    })

    }

    }

    })

    },

    })

    },

    //后台

     

    //微信支付
        public function Wx_Pay(){
            $request=Request::instance();
            $fee=$request->param('fee');
            $details=$request->param('details');//商品的详情,比如iPhone8,紫色
           // $fee = 0.01;//举例充值0.01
            $appid =        'appid';//appid
            $body =        $details;// '金邦汇商城';//'【自己填写】'
            $mch_id =       '1486742092';//'你的商户号【自己填写】'
            $nonce_str =    $this->nonce_str();//随机字符串
            $notify_url =   'https://zys.jinbh.cn/admin/Api/Wx_Speech';//回调的url【自己填写】';
            $openid =       $request->param('openid');//'用户的openid【自己填写】';
            $out_trade_no = $this->order_number($openid);//商户订单号
            $spbill_create_ip = '123.206.45.131';//'服务器的ip【自己填写】';
            $total_fee =    $fee*100;//因为充值金额最小是1 而且单位为分 如果是充值1元所以这里需要*100
            $trade_type = 'JSAPI';//交易类型 默认
            //这里是按照顺序的 因为下面的签名是按照顺序 排序错误 肯定出错
            $post['appid'] = $appid;
            $post['body'] = $body;
            
            $post['mch_id'] = $mch_id;
          
            $post['nonce_str'] = $nonce_str;//随机字符串
          
            $post['notify_url'] = $notify_url;
          
            $post['openid'] = $openid;
          
            $post['out_trade_no'] = $out_trade_no;
          
            $post['spbill_create_ip'] = $spbill_create_ip;//终端的ip
          
            $post['total_fee'] = $total_fee;//总金额 最低为一块钱 必须是整数
         
            $post['trade_type'] = $trade_type;
            $sign = $this->sign($post);//签名
            $post_xml = '<xml>
               <appid>'.$appid.'</appid>
               <body>'.$body.'</body>
               <mch_id>'.$mch_id.'</mch_id>
               <nonce_str>'.$nonce_str.'</nonce_str>
               <notify_url>'.$notify_url.'</notify_url>
               <openid>'.$openid.'</openid>
               <out_trade_no>'.$out_trade_no.'</out_trade_no>
               <spbill_create_ip>'.$spbill_create_ip.'</spbill_create_ip>
               <total_fee>'.$total_fee.'</total_fee>
               <trade_type>'.$trade_type.'</trade_type>
               <sign>'.$sign.'</sign>
            </xml> ';
            //统一接口prepay_id
            $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
            $xml = $this->http_request($url,$post_xml);
            $array = $this->xml($xml);//全要大写
            if($array['RETURN_CODE'] == 'SUCCESS' && $array['RESULT_CODE'] == 'SUCCESS'){
                $time = time();
                $tmp='';//临时数组用于签名
                $tmp['appId'] = $appid;
                $tmp['nonceStr'] = $nonce_str;
                $tmp['package'] = 'prepay_id='.$array['PREPAY_ID'];
                $tmp['signType'] = 'MD5';
                $tmp['timeStamp'] = "$time";
    
                $data['state'] = 1;
                $data['timeStamp'] = "$time";//时间戳
                $data['nonceStr'] = $nonce_str;//随机字符串
                $data['signType'] = 'MD5';//签名算法,暂支持 MD5
                $data['package'] = 'prepay_id='.$array['PREPAY_ID'];//统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=*
                $data['paySign'] = $this->sign($tmp);//签名,具体签名方案参见微信公众号支付帮助文档;
                $data['out_trade_no'] = $out_trade_no;
    
            }else{
                $data['state'] = 0;
                $data['text'] = "错误";
                $data['RETURN_CODE'] = $array['RETURN_CODE'];
                $data['RETURN_MSG'] = $array['RETURN_MSG'];
            }
          echo json_encode($data);
        }
    
    
    //随机32位字符串
        private function nonce_str(){
            $result = '';
            $str = 'QWERTYUIOPASDFGHJKLZXVBNMqwertyuioplkjhgfdsamnbvcxz';
            for ($i=0;$i<32;$i++){
                $result .= $str[rand(0,48)];
            }
            return $result;
        }
    
    
    //生成订单号
        private function order_number($openid){
            //date('Ymd',time()).time().rand(10,99);//18位
            return md5($openid.time().rand(10,99));//32位
        }
    
    
    
    
    //签名 $data要先排好顺序
        public function sign($data)
        {
            $stringA = '';
            foreach ($data as $key => $value) {
                if (!$value) continue;
                if ($stringA) $stringA .= '&' . $key . "=" . $value;
                else $stringA = $key . "=" . $value;
            }
            $wx_key = 'Zhangyusheng19810318015729366660';//申请支付后有给予一个商户账号和密码,登陆后自己设置key
            $stringSignTemp = $stringA . '&key=' . $wx_key;//申请支付后有给予一个商户账号和密码,登陆后自己设置key 
          return strtoupper(md5($stringSignTemp));
        }
    
    //curl请求啊
            function http_request($url, $data = null, $headers = array())
            {
                $curl = curl_init();
                if (count($headers) >= 1) {
                    curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
                }
                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;
            }
    
    //获取xml
            private function xml($xml){
                $p = xml_parser_create();
                xml_parse_into_struct($p, $xml, $vals, $index);
                xml_parser_free($p);
                $data = "";
                foreach ($index as $key=>$value) {
                    if($key == 'xml' || $key == 'XML') continue;
                    $tag = $vals[$value[0]]['tag'];
                    $value = $vals[$value[0]]['value'];
                    $data[$tag] = $value;
                }
                return $data;
            }
    //微信支付结束
    展开全文
  • 微信小程序调用微信支付接口

    万次阅读 多人点赞 2018-12-05 15:17:12
    前言:应项目要求,需要使用微信小程序做支付,写完后告知手续费太高方案不予通过(宝宝心里苦,但宝宝不说)。此次开发在因站在巨人的肩膀上顺利完成。 微信支付文档传送门:...

    前言:应项目要求,需要使用微信小程序做支付,写完后告知手续费太高方案不予通过(宝宝心里苦,但宝宝不说)。此次开发在因站在巨人的肩膀上顺利完成。

    微信支付文档传送门:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_3

    1.开发工具:

    Eclipse+Tomcat+微信web开发工具

    2.开发环境:

    java+maven

    3.开发前准备:

    3.1 所需材料

    小程序的appid,APPsecret,支付商户号(mch_id),商户密钥(key),付款用户的openid。

    申请接入微信商户地址:https://pay.weixin.qq.com/static/applyment_guide/applyment_detail_miniapp.shtml

    3.2 开发模式

    本次开发采用的开发模式是:普通模式,适用于有自己开发团队或外包开发商的直连商户收款。开发者申请自己的appid和mch_id,两者需具备绑定关系,以此来使用微信支付提供的开放接口,对用户提供服务。

     

    4 开发

    4.1 小程序端

    wx.request({
    
        url: address + 'wxPay',
    
        data: {
    
            openId: openId
        
            // amount: amount,
    
            // openId: openId
    
        },
    
        header: {
    
            'content-type': 'application/x-www-form-urlencoded' // 默认值
        
        },
    
        method: "POST",
    
        success: function (res) {
    
            console.log(res);
    
            that.doWxPay(res.data);
        },
    
        fail: function (err) {
    
            wx.showToast({
    
                icon: "none",
    
                title: '服务器异常,清稍候再试'
    
            })
    
        },
    
    });
    
    
    
    doWxPay(param) {
    
    //小程序发起微信支付
    
    wx.requestPayment({
    
    timeStamp: param.data.timeStamp,//记住,这边的timeStamp一定要是字符串类型的,不然会报错
    
    nonceStr: param.data.nonceStr,
    
    package: param.data.package,
    
    signType: 'MD5',
    
    paySign: param.data.paySign,
    
    success: function (event) {
    
    // success
    
    console.log(event);
    
    
    
    wx.showToast({
    
    title: '支付成功',
    
    icon: 'success',
    
    duration: 2000
    
    });
    
    },
    
    fail: function (error) {
    
    // fail
    
    console.log("支付失败")
    
    console.log(error)
    
    },
    
    complete: function () {
    
    // complete
    
    console.log("pay complete")
    
    }
    
    });
    
    },

    4.2 java后台

    4.2.1 PayUtil.java

    private static Logger logger = Logger.getLogger(PayUtil.class);
    public static JSONObject wxPay(String openid,HttpServletRequest request){
    JSONObject json = new JSONObject();
            try{
                //生成的随机字符串
                String nonce_str = Util.getRandomStringByLength(32);
                //商品名称 
                String body = new String(WXConst.title.getBytes("ISO-8859-1"),"UTF-8");
                //获取本机的ip地址
                String spbill_create_ip = Util.getIpAddr(request);
                String orderNo = WXConst.orderNo;
                String money = "1";//支付金额,单位:分,这边需要转成字符串类型,否则后面的签名会失败
    
                Map<String, String> packageParams = new HashMap<String, String>();
                packageParams.put("appid", WXConst.appId);
                packageParams.put("mch_id", WXConst.mch_id);
                packageParams.put("nonce_str", nonce_str);
                packageParams.put("body", body);
                packageParams.put("out_trade_no", orderNo);//商户订单号
                packageParams.put("total_fee", money);
                packageParams.put("spbill_create_ip", spbill_create_ip);
                packageParams.put("notify_url", WXConst.notify_url);
                packageParams.put("trade_type", WXConst.TRADETYPE);
                packageParams.put("openid", openid);
    
    
                // 除去数组中的空值和签名参数
                packageParams = PayUtil.paraFilter(packageParams);
                String prestr = PayUtil.createLinkString(packageParams); // 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
    
    
                //MD5运算生成签名,这里是第一次签名,用于调用统一下单接口
                String mysign = PayUtil.sign(prestr, WXConst.key, "utf-8").toUpperCase();
                logger.info("=======================第一次签名:" + mysign + "=====================");
    
    
                //拼接统一下单接口使用的xml数据,要将上一步生成的签名一起拼接进去
                String xml = "<xml version='1.0' encoding='gbk'>" + "<appid>" + WXConst.appId + "</appid>"
                        + "<body><![CDATA[" + body + "]]></body>"
                        + "<mch_id>" + WXConst.mch_id + "</mch_id>"
                        + "<nonce_str>" + nonce_str + "</nonce_str>"
                        + "<notify_url>" + WXConst.notify_url + "</notify_url>"
                        + "<openid>" + openid + "</openid>"
                        + "<out_trade_no>" + orderNo + "</out_trade_no>"
                        + "<spbill_create_ip>" + spbill_create_ip + "</spbill_create_ip>"
                        + "<total_fee>" + money + "</total_fee>"
                        + "<trade_type>" + WXConst.TRADETYPE + "</trade_type>"
                        + "<sign>" + mysign + "</sign>"
                        + "</xml>";
    
    
                System.out.println("调试模式_统一下单接口 请求XML数据:" + xml);
    
    
                //调用统一下单接口,并接受返回的结果
                String result = PayUtil.httpRequest(WXConst.pay_url, "POST", xml);
    
    
                System.out.println("调试模式_统一下单接口 返回XML数据:" + result);
    
    
                // 将解析结果存储在HashMap中
                Map map = PayUtil.doXMLParse(result);
    
    
                String return_code = (String) map.get("return_code");//返回状态码
    
    
                //返回给移动端需要的参数
                Map<String, Object> response = new HashMap<String, Object>();
                if(return_code == "SUCCESS" || return_code.equals(return_code)){
                    // 业务结果
                    String prepay_id = (String) map.get("prepay_id");//返回的预付单信息
                    response.put("nonceStr", nonce_str);
                    response.put("package", "prepay_id=" + prepay_id);
                    Long timeStamp = System.currentTimeMillis() / 1000;
                    response.put("timeStamp", timeStamp + "");//这边要将返回的时间戳转化成字符串,不然小程序端调用wx.requestPayment方法会报签名错误
    
    
                    String stringSignTemp = "appId=" + WXConst.appId + "&nonceStr=" + nonce_str + "&package=prepay_id=" + prepay_id+ "&signType=" + WXConst.SIGNTYPE + "&timeStamp=" + timeStamp;
                    //再次签名,这个签名用于小程序端调用wx.requesetPayment方法
                    String paySign = PayUtil.sign(stringSignTemp, WXConst.key, "utf-8").toUpperCase();
                    logger.info("=======================第二次签名:" + paySign + "=====================");
    
    
                    response.put("paySign", paySign);
    
    
                    //更新订单信息
                    //业务逻辑代码
                }
    
    
                response.put("appid", WXConst.appId);
                json.put("errMsg", "OK");
                //json.setSuccess(true);
                json.put("data", response);
                //json.setData(response);
            }catch(Exception e){
                e.printStackTrace();
                json.put("errMsg", "Failed");
                //json.setSuccess(false);
                //json.setMsg("发起失败");
            }
            return json;
        }
    
    
    
    /**  
         * 签名字符串  
         * @param text需要签名的字符串  
         * @param key 密钥  
         * @param input_charset编码格式  
         * @return 签名结果  
         */   
        public static String sign(String text, String key, String input_charset) {   
            text = text + "&key=" + key;   
            return DigestUtils.md5Hex(getContentBytes(text, input_charset));   
        }   
        /**  
         * 签名字符串  
         * @param text需要签名的字符串  
         * @param sign 签名结果  
         * @param key密钥  
         * @param input_charset 编码格式  
         * @return 签名结果  
         */   
        public static boolean verify(String text, String sign, String key, String input_charset) {   
            text = text + key;   
            String mysign = DigestUtils.md5Hex(getContentBytes(text, input_charset));   
            if (mysign.equals(sign)) {   
                return true;   
            } else {   
                return false;   
            }   
        }   
        /**  
         * @param content  
         * @param charset  
         * @return  
         * @throws SignatureException  
         * @throws UnsupportedEncodingException  
         */   
        public static byte[] getContentBytes(String content, String charset) {   
            if (charset == null || "".equals(charset)) {   
                return content.getBytes();   
            }   
            try {   
                return content.getBytes(charset);   
            } catch (UnsupportedEncodingException e) {   
                throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);   
            }   
        }   
        /**  
         * 生成6位或10位随机数 param codeLength(多少位)  
         * @return  
         */   
        public static String createCode(int codeLength) {   
            String code = "";   
            for (int i = 0; i < codeLength; i++) {   
                code += (int) (Math.random() * 9);   
            }   
            return code;   
        }   
        @SuppressWarnings("unused")
    private static boolean isValidChar(char ch) {   
            if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'))   
                return true;   
            if ((ch >= 0x4e00 && ch <= 0x7fff) || (ch >= 0x8000 && ch <= 0x952f))   
                return true;// 简体中文汉字编码   
            return false;   
        }   
        /**  
         * 除去数组中的空值和签名参数  
         * @param sArray 签名参数组  
         * @return 去掉空值与签名参数后的新签名参数组  
         */   
        public static Map<String, String> paraFilter(Map<String, String> sArray) {   
            Map<String, String> result = new HashMap<String, String>();   
            if (sArray == null || sArray.size() <= 0) {   
                return result;   
            }   
            for (String key : sArray.keySet()) {   
                String value = sArray.get(key);   
                if (value == null || value.equals("") || key.equalsIgnoreCase("sign")   
                        || key.equalsIgnoreCase("sign_type")) {   
                    continue;   
                }   
                result.put(key, value);   
            }   
            return result;   
        }   
        /**  
         * 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串  
         * @param params 需要排序并参与字符拼接的参数组  
         * @return 拼接后字符串  
         */   
        public static String createLinkString(Map<String, String> params) {   
            List<String> keys = new ArrayList<String>(params.keySet());   
            Collections.sort(keys);   
            String prestr = "";   
            for (int i = 0; i < keys.size(); i++) {   
                String key = keys.get(i);   
                String value = params.get(key);   
                if (i == keys.size() - 1) {// 拼接时,不包括最后一个&字符   
                    prestr = prestr + key + "=" + value;   
                } else {   
                    prestr = prestr + key + "=" + value + "&";   
                }   
            }   
            return prestr;   
        }   
        /**  
         *  
         * @param requestUrl请求地址  
         * @param requestMethod请求方法  
         * @param outputStr参数  
         */   
        public static String httpRequest(String requestUrl,String requestMethod,String outputStr){   
            // 创建SSLContext   
            StringBuffer buffer = null;   
            try{   
            URL url = new URL(requestUrl);   
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();   
            conn.setRequestMethod(requestMethod);   
            conn.setDoOutput(true);   
            conn.setDoInput(true);   
            conn.connect();   
            //往服务器端写内容   
            if(null !=outputStr){   
                OutputStream os=conn.getOutputStream();   
                os.write(outputStr.getBytes("utf-8"));   
                os.close();   
            }   
            // 读取服务器端返回的内容   
            InputStream is = conn.getInputStream();   
            InputStreamReader isr = new InputStreamReader(is, "utf-8");   
            BufferedReader br = new BufferedReader(isr);   
            buffer = new StringBuffer();   
            String line = null;   
            while ((line = br.readLine()) != null) {   
            buffer.append(line);   
            }   
            br.close();
            }catch(Exception e){   
                e.printStackTrace();   
            }
            return buffer.toString();
        }     
        public static String urlEncodeUTF8(String source){   
            String result=source;   
            try {   
                result=java.net.URLEncoder.encode(source, "UTF-8");   
            } catch (UnsupportedEncodingException e) {   
                // TODO Auto-generated catch block   
                e.printStackTrace();   
            }   
            return result;   
        } 
        /**
    * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。
    * @param strxml
    * @return
    * @throws JDOMException
    * @throws IOException
    */
    public static Map doXMLParse(String strxml) throws Exception {
        if(null == strxml || "".equals(strxml)) {
            return null;
           }
    
        Map m = new HashMap();
        InputStream in = String2Inputstream(strxml);
        SAXBuilder builder = new SAXBuilder();
        Document doc = builder.build(in);
        Element root = doc.getRootElement();
        List list = root.getChildren();
        Iterator it = list.iterator();
        while(it.hasNext()) {
            Element e = (Element) it.next();
            String k = e.getName();
            String v = "";
            List children = e.getChildren();
            if(children.isEmpty()) {
                v = e.getTextNormalize();
            } else {
                v = getChildrenText(children);
        }
    
        m.put(k, v);
    }
    
    //关闭流
    in.close();
    
    return m;
    }
    /**
    * 获取子结点的xml
    * @param children
    * @return String
    */
    public static String getChildrenText(List children) {
        StringBuffer sb = new StringBuffer();
        if(!children.isEmpty()) {
        Iterator it = children.iterator();
        while(it.hasNext()) {
            Element e = (Element) it.next();
            String name = e.getName();
            String value = e.getTextNormalize();
            List list = e.getChildren();
            sb.append("<" + name + ">");
            if(!list.isEmpty()) {
                sb.append(getChildrenText(list));
            }
            sb.append(value);
            sb.append("</" + name + ">");
        }
    }
    
        return sb.toString();
    }
    public static InputStream String2Inputstream(String str) {
        return new ByteArrayInputStream(str.getBytes());
    }
    
    
    
    
    
    public static void wxNotify(HttpServletRequest request,HttpServletResponse response) throws Exception{  
    BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream)request.getInputStream()));
            String line = null;
            StringBuilder sb = new StringBuilder();
            while((line = br.readLine())!=null){
                sb.append(line);
            }
            br.close();
            //sb为微信返回的xml
            String notityXml = sb.toString();
            String resXml = "";
            System.out.println("接收到的报文:" + notityXml);
    
    
            Map map = PayUtil.doXMLParse(notityXml);
    
    
            String returnCode = (String) map.get("return_code");
            if("SUCCESS".equals(returnCode)){
                //验证签名是否正确
                if(PayUtil.verify(PayUtil.createLinkString(map), (String)map.get("sign"), WXConst.key, "utf-8")){
                    /**此处添加自己的业务逻辑代码start**/
    
    
    
    
                    /**此处添加自己的业务逻辑代码end**/
    
    
                    //通知微信服务器已经支付成功
                    resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                            + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
                }
            }else{
                resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                        + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
            }
            System.out.println(resXml);
            System.out.println("微信支付回调数据结束");
    
    
            BufferedOutputStream out = new BufferedOutputStream(
                    response.getOutputStream());
            out.write(resXml.getBytes());
            out.flush();
            out.close();  
        }

     

     

    4.2.2 Util.java

    /**
         * Util工具类方法
         * 获取一定长度的随机字符串,范围0-9,a-z
         * @param length:指定字符串长度
         * @return 一定长度的随机字符串
         */
        public static String getRandomStringByLength(int length) {
            String base = "abcdefghijklmnopqrstuvwxyz0123456789";
            Random random = new Random();
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < length; i++) {
                int number = random.nextInt(base.length());
                sb.append(base.charAt(number));
            }
            return sb.toString();
        }
        
        
        /**
         * Util工具类方法
         * 获取真实的ip地址
         * @param request
         * @return
         */
        public static String getIpAddr(HttpServletRequest request) {
            String ip = request.getHeader("X-Forwarded-For");
            if(StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)){
                //多次反向代理后会有多个ip值,第一个ip才是真实ip
                int index = ip.indexOf(",");
                if(index != -1){
                    return ip.substring(0,index);
                }else{
                    return ip;
                }
            }
            ip = request.getHeader("X-Real-IP");
            if(StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)){
                return ip;
            }
            return request.getRemoteAddr();
    
        }

     

    4.2.3 WXConst.java

        

    //微信小程序appid
    public static String appId = "";
    //微信小程序appsecret
    public static String appSecret = "";
    //微信支付主体
    public static String title = "";
    public static String orderNo = "";
    //微信商户号
    public static String mch_id="";
    //微信支付的商户密钥
    public static final String key = "";
    //获取微信Openid的请求地址
    public static String WxGetOpenIdUrl = "";
    //支付成功后的服务器回调url
    public static final String notify_url="https://api.weixin.qq.com/sns/jscode2session";
    //签名方式
    public static final String SIGNTYPE = "MD5";
    //交易类型
    public static final String TRADETYPE = "JSAPI";
    //微信统一下单接口地址
    public static final String pay_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";

     

    5 可能出现的问题

    5.1 商户号

    会出现一个什么异常我忘了,重置一下微信商户密钥就好了

    5.2 中文参数

    String body = new String(WXConst.title.getBytes("ISO-8859-1"),"UTF-8");

    这行很重要,如果报参数索引-2异常,很可能是出现了中文,对中文进行如上处理即可通过。

    5.3 invalid spbill_create_ip

    使用微信web开发工具直接测试的,出现了这个问题,调试记得用真机哦。

    整个小程序前后端一个人开发,测试成功上线前夕又嫌弃微信支付收取的手续费(0.6%)太高,结算周期(T+7)太长,所以就被无情抛弃了,这个月项目重启(2018-11)和工商银行达成一致,直接转账到对公账户,目前项目进展顺利已上线。改需求请先扫码(小声bb)

    展开全文
  • 小程序微信支付 实例配置详解

    万次阅读 热门讨论 2019-07-05 12:24:01
    近期进行小程序的开发,毕竟是商城项目的开发,最后牵扯到的微信支付是必要的个人开发过程中也是遇到各种问题。在此,进行代码的详细配置,以方便小程序新手的快速操作 使用语言:PHP 框架:ThinkPHP 3.2 整理时间...

    ★ 背景

    • 近期进行小程序的开发,毕竟是商城项目的开发,最后牵扯到的微信支付是必要的
    • 个人开发过程中也是遇到各种问题,在此,我根据自己的实际操作,进行了代码的详细配置,以方便小程序新手的快速操作
    -  使用语言:PHP             # PHP世界上最好的语言 HaHahahaaha
    -  使用框架:ThinkPHP 3.2    # 版本有点低而已,没啥大碍
    -  测试工具:微信开发者工具    # 其实还挺好用
    -  整理时间:2018-07-07      # 有问题,就会一直更新
    

    tip: 【代码都是可转化的,即便是 ThinkPHP5.0+ 还是 Laravel框架,相对熟悉 PHP 代码语法的,进行转化也只是分分钟的事哦!】

    一、开发前的准备

    ①. 开发步骤

    • 如果开发者已做过 JSAPIJSSDK 调起微信支付,接入小程序支付非常相似,以下是三种接入方式的对比:

    如此看来,小程序要想集成支付功能,倒是简单了

    ②. 阅读业务流程图

    • 本人强烈推荐阅读这个图示,流程明确了,代码逻辑自然也就理顺了!

    ③. 小程序支付业务

    • 此处,小程序官方已做了详细说明 —— 业务说明
    # 很多人这一步还没有完成,就咔咔咔的测试支付功能,显然是太急于求成了,比如:我!
    > 注意:
    > 1. 要开通微信支付功能(一般有两三天的审核时间)
    > 2. 本人开通后,选择的是 “绑定一个已有的微信支付商户号”,也就几分钟的事
    

    • 此处请阅读官方文末的注意事项【重要】:
    1 appid 必须为最后拉起收银台的小程序appid; 
    		# 这句话感觉不说还好,一说更容易引起多余的考虑(忽视)
    
    2 mch_id 为和 appid 成对绑定的支付商户号,收款资金会进入该商户号;
    		# 此处我直接使用了所绑定的商户号中的 mch_id
    
    3 trade_type 请填写"JSAPI"; 
    		# 可暂时忽略,因为我在代码中已进行了配置
    
    4 openid 为 appid 对应的用户标识,即使用 "wx.login" 接口获得的 openid 
    		# 可参考我的 payment/index.js 代码
    		# 另一种情况,如果项目数据库中已保存了该用户的openid字段,可自行获取
    

    二、小程序端代码配置指导

    • 这里进行配置的代码,都在附录源码包的 wxMini-PayDemo\wxChat 目录下

    为了项目代码的 通用性/易管理性,我自行提取出了两个主要的公共文件 config.jsutil.js;

    ①. utils下 config.js 文件的使用

    • config.js 文件中,主要就是配置一些公共访问路径之类的数据,方便后期代码上线后的链接更改
    • 所以,对于其中的 restUrlimgServer 修改为自己的服务器地址即可
    > 注意一点:
    我的 "restUrl" 是对应于我的小程序 Api 接口路径的,举个例子:
    我的支付回调路径为 "https://www.mySercver.com/WxApi/Pay/notify" 
    

    ②. utils下 util.js 文件的使用

    • 这个是和 config.js 文件在同一目录下的公共文件
    • 其实就是整合了三个主要的方法,需要注意的是:如果你有所补充,记得在文件的最后进行 “exports” 输出就好
    module.exports = {
      http_get: http_get,
      http_post: http_post,
      showToast: showToast,
    }
    

    ③. payment/index.js 文件的使用

    • 此文件作为 小程序微信支付前端的核心文件
    • 在保证你的各个文件目录对应配置正确的情况下,只需在进行支付唤醒时,调用其中的 btnClickToPay() 方法即可:
    • 当然,我只是随便定的一个方法,实际使用的时候,其实就是以类似的形式,去调用后面的 wxPay()方法呗!

    三、服务端代码文件的使用指导

    • 这里进行配置的代码,都在源码包的 wxMini-PayDemo\Server-PHP 目录下

    声明:
    因为本人所提供的代码是基于 ThinkPHP3.2 框架编写整理的,所以对于使用过 ThinkPHPLaravel 框架的 PHPer 来说,简单明了,可根据自己的框架进行调整适配,所以,此处讲的可能不会太过琐碎

    ①. 公共配置文件的数据补充

    • 此为源代码中的 "wxMini-PayDemo\Server-PHP\Conf\config.php",此文件代码比较少,我直接进行展示:
    return array(
        //'配置项'=>'配置值'
        'wxPay' => [
            'appid' => 'wx8787xxxxxxxxxxxxx',//TODO 此处使用的是小程序的 APPID
            'app_secret' => '0a7xxxxxxxxxxxxxxxxxxxxxxxxxxxxx622', //小程序的应用密钥
            'pay_mchid' => '13xxxxxx02', // 微信支付MCHID 商户收款账号
            'pay_apikey' => '1qaxxxxxxxxxxxxxxxxxxxxxhgf5', // 微信支付KEY
            'notify_url' => 'https://www.mySercver.com/WxApi/Pay/notify', // 微信支付成功后进行回调的链接
            'login_url' => "https://api.weixin.qq.com/sns/jscode2session?" .
                "appid=%s&secret=%s&js_code=%s&grant_type=authorization_code", // 微信使用code换取用户openid及session_key的url地址
        ],
    );
    
    • 对于上述配置信息的来源,应该没啥疑问吧?
    注意一点:
    "notify_url" 作为支付回调的链接地址,要求配置成自己的服务器路径 
    	;#同时注意协议的要求 “https” 
    
    小程序官方要求:
    	;# 需要进行服务器域名的配置
    	;# 操作位置为 “小程序(微信公众平台)/设置/开发设置”中的“服务器域名->request 合法域名”
    

    ②. 公共方法 function.php 的补充

    • 对于本人的逻辑处理中,其实只有一个方法 curl_get(), 并且只在 PayController.class.phpgetOpenID() 方法中进行了一次调用,也可以自行提取使用的

    ③. 核心处理文件 PayController.class.php

    此文件代码已做了详细处理,在你正确放置后,需要注意的几点如下:

    • (1). 注意命名空间 "namespace" 与自己业务代码的对应
    • (2). 在 "prepay()" 方法中,因为不同的业务都会有属于自己的判断处理逻辑,
    所以,在使用时完全可以替换掉所调用的 "prepayOrderDeal()" 方法  ;# 相信没多大歧义吧!
    		 #【在此处,我建议进行一下微信支付金额的校对】
    		 # 比如,通过订单号到你的项目数据库中,查询出需要支付的金额再与此比较,
    		 # 只有符合你的要求才可以进行微信支付的下单操作
    
    • (3). 在 "pay()" 方法中

    建议对应当前的订单号,保存微信支付返回的 prepay_id

    • (4). 再有就是,在 "notify()" 这个回调方法中
    一定会涉及到自己业务的更新处理逻辑
        所以被调用的 "payNotifyOrderDeal()"方法中就可以改成你自己的业务逻辑了 (此处是可以自行补充的)
    

    	注意,此处传入的 "$result" 参数中,我主要使用的就是其中的 "out_trade_no" 和 "total_fee" 
    		# 包含着微信支付的众多信息,可自行提取
    	前者用于匹配我对该已支付订单的后续更新操作 
    		#【提示:我在使用时需要使用 "M" 进行字符串的截取才是我自己业务的实际订单编号哦!】;
    	后者是实际微信消费的金额,可用于数据表的记录,以方便对账人员的校对工作
    

    补充:

    1. 为了方便后期 微信退款功能 的扩展,建议对应订单保存回调得到的 $result
    2. 可以将其转化为 json 字符串形式 $wx_pay_result_json = json_encode($result);, 然后存储在订单表中,比如:
    3. 如果,直接进行微信退款功能的实现,请完成后,参考:小程序 微信退款功能实现讲解 (PHP方式)

    四、使用及测试效果

    ①. 测试效果

    • 在我的小程序项目中,唤醒的效果(开发工具中)如下:

    • 如果是在自己的手机端进行测试,在保证你的域名配置正确的情况下,唤醒的样式就是常见的样子:

    ②. 补充说明

    - 相信在实际配置使用的过程中一定会出现各种问题,我也是一点点的梳理排错过来的
    - 前面的多是些配置问题的规范,如果到了最后的唤醒阶段,出现的问题要注意查看开发工具的控制台,
    - 其中会有比较详细的报错信息,然后再进行排查解决
    - 有何问题,欢迎指摘,祝你配置顺利咯!
    

    ☆ 附录:

    ①. >>> Github 源码下载参考

    再做补充:如果,直接进行微信退款功能的实现,请完成后,参考:小程序 微信退款功能实现讲解 (PHP方式)

    ②. 总结

    • 通过对以上操作的梳理,可以提取出主要的几个步骤:
    -  小程序要开通你的微信支付功能 # 需要审核时间的
    -  审核通过后,紧接着进行"开通"操作 #可有两种开通方式进行选择的
    -  前后端重要信息配置完毕
    -  补充自己的特有逻辑处理操作 #pay/prepayOrderDeal()和 pay/payNotifyOrderDeal()
    -  支付回调成功后,进行后续的订单(项目服务器)查询操作
    
    展开全文
  • 详解微信小程序支付流程

    万次阅读 多人点赞 2018-07-02 18:29:54
    首先先把小程序微信支付的图搬过来:相信会来查百度的同学们基本都是对文档的说明不是很理解。我下面大概总结一下整个业务逻辑的过程。微信小程序的商户系统一般是以接口的形式开发的,小程序通过调用与后端约定好的...

      花了几天把小程序的支付模块接口写了一下,可能有着公众号开发的一点经验,没有入太多的坑,在此我想记录一下整个流程。

    首先先把小程序微信支付的图搬过来:


    相信会来查百度的同学们基本都是对文档的说明不是很理解。我下面大概总结一下整个业务逻辑的过程。

    微信小程序的商户系统一般是以接口的形式开发的,小程序通过调用与后端约定好的接口进行参数的传递以及数据的接收。在小程序支付这块,还需要跟微信服务器进行交互。过程大致是这样的:

    一.小程序调用登录接口获取code,传递给商户服务器用来获取用户的openID

     我们知道在微信平台中,同一个公众号的openID都是不同的,它是用户身份识别的id,也就是说,我们通过openID来区分不同的用户,这个有微信开发基础的应该都很熟悉。为了知道谁在支付,我们需要先获取当前用户的openid,那么openID应该怎么获取呢?看下图:


    1. 小程序调用wx.login() 获取 临时登录凭证code ,并回传到开发者服务器。

    2. 开发者服务器以code换取 用户唯一标识openid 和 会话密钥session_key

    看不懂吗?不急,听我慢慢解释,这个业务流程大致就是首先你得先在小程序的代码中调用wx.login()来向微信获取到code,拿到了之后把code通过request传给商户服务器,再由商户服务器通过骚操作来跟微信服务器要session_key和openID。

    伪代码如下(小程序端):

    getToken: function () {
        //调用登录接口
        wx.login({
          success: function (res) {
            var code = res.code;
            wx.request({
              url: 商户服务器接口地址, 
              data: {
                code: code
              },
              method: 'POST', 
              success: function (res) { 
                wx.setStorageSync('token', res.data.token); //存在小程序缓存中
              },
              fail: function (res) {
                console.log(res.data);
              }
            })
          }
        })
      }

    调用这几行代码就可以向跟微信服务器要code,并且将code传到商户服务器中,记住这里最好使用post发送请求,安全性的东西我应该不用讲了,因为避免其他人滥用接口,于是我们使用token来进行验证。并将商户服务器返回的token存在小程序缓存中。

    那么服务器端应该怎么做呢?

    我门通过小程序提交的code,和小程序的APPID以及APPSECRET和拼接下列的url,并用curl进行get请求。

    https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code

    返回的数据是一个json对象,我门通过使用json_decode(JSON,true)解析为数组,数据包括用户的openID以及session_key,获取到了后我们应该将openID存入数据库中,它代表着用户的身份,那么令牌应该怎么生成呢。

    二.token的生成以及缓存

    我们根据一个用户表将id和openid联系起来,对应openID的id则是用户的uid,我们可以这么封装

    //要缓存的数据数组
    $cacheValue = $result;   //包含openID和session_key
    $cacheValue['uid'] =$uid;   //用户id
    
    $cacheValue['scope'] =ScopeEnum::User;   //用户权限级别

    缓存的方式我们可以选择redis,memcache, 文件缓存等等,采用键值对(key-value)的方式进行存储,记得设置好过期时间。这里的key我们用token来赋值,token可以通过这样的方式进行生成:

    //获取32位随机字符串
    $str = getRandChar(32);   //自定义方法生成32位随机串
    //三组字符串进行md5加密
    $timeStamp =$_SERVER['REQUEST_TIME_FLOAT'];
    //salt
    $salt = config('secure.token_salt'); //随机字符串
    //返回token
    
    return md5($str.$timeStamp.$salt);

    这种算法基本保障了token的唯一性。因为值是我们获取到的openID和session_key所在的数组,所以需要将数组转成json才能存进去。以后的代码当我们需要openID或者uid等时可以直接通过取缓存的方式来取。

    三,调用统一下单接口,获取prepay_id,再次签名

     在你写完了订单操作后,如何让用户支付订单费用呢?这里就是重点了,我一步一步来说:

    1.下载微信JS-SDK:

    (https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1)

    解压打开进入lib文件夹中:


    我们需要将lib中的文件放到我们的框架中,例如我使用的是tp5,就放到extend下,最好是在extend下建个子文件夹。其中WxPay.Api.php是入口,WxPay.Config.php是配置文件。下好后需要改动一些地方。在WxPay.Config.php中修改下列的东西改成你的。


    然后在WxPay.Api.php中require一下WxPay.Notify.php,如图:

    在某个控制器或者服务层的代码先是用Loader::import()引入WxPay.Api.php,相当于五个都引入了。

    2.调用统一下单api

    这里要啰嗦的是,如何你写的是有关商品买卖的小程序,那么需要在支付前再次检测一下库存量,因为用户下完订单后不一定马上就会付款,如果在付款的期间库存量没了便会出现问题。业务逻辑我就不说太多了,这取决于你写代码的严谨性。

    在我们引入了上面那个文件后,先实例化这个类WxPayUnifiedOrder,把需要的参数通过调用对应的方法传入。

    伪代码如下:

     //调用微信支付统一下单接口
            $wxOrderData = new \WxPayUnifiedOrder();
            //设置相关参数
            $wxOrderData->SetOut_trade_no($this->orderNO);
            $wxOrderData->SetTrade_type('JSAPI');
            $wxOrderData->SetTotal_fee($totalPrice * 100); //这里的价格单位是分
            $wxOrderData->SetBody('Mc');
            $wxOrderData->SetOpenid($openid);
            $wxOrderData->SetNotify_url(config('secure.pay_back_url'));//支付回调

    其中第一个是你的订单号,订单号的生成方法可以自定义,第二个是死参数,第三个是总订单价格,第四个是名称如果是中文的话要转码,第四个是openID,这个这时候就可以从缓存中取了。最后一个是支付回调,就是支付成功后微信要访问的地址。必须是公网能访问的,或者你使用ngrok来进行反向代理转发本地的服务器。

    参数设置好了之后,就直接调用SDK的方法了

     $wxOrder = \WxPayApi::unifiedOrder($wxOrderData);
    如果参数没有错误的话,返回的数据中会含有prepay_id,这个是我们需要的参数。


    3.再次签名
    //  提交JSAPI输入对象
            $jsApiPayData = new \WxPayJsApiPay();
            //设置appid
            $jsApiPayData->SetAppid(config('wx.app_id'));
            //timeStamp
            $jsApiPayData->SetTimeStamp((string)time());
            //随机串
            $randStr = md5(time().mt_rand(0,1000));
            $jsApiPayData->SetNonceStr($randStr);
            //数据报
            $jsApiPayData->SetPackage('prepay_id='.$wxOrder['prepay_id']);
            //类型
            $jsApiPayData->SetSignType('MD5');
            //生成签名
            $sign  = $jsApiPayData->MakeSign();
            //获得签名数组
            $signData = $jsApiPayData->GetValues();
            //增加字段paySign
            $signData['paySign']=$sign;
            //删除signData中的app_Id字段
            unset($signData['appId']);
            return $signData;

    再次签名完成后,就把五个参数返回给小程序。

    四,小程序获取五个参数后,鉴权调起支付

    伪代码(小程序端)

      pay: function () {
        var token = wx.getStorageSync('token');
        var that = this;
      
        wx.request({
          url: baseUrl + '/order',
          header: {
            token: token
          },
          data: {   //产品的数据
            products:
            [
              {
                product_id: 1, count: 1
              },
              
              {
                product_id: 2, count: 1
              }
            ]
          },
          method: 'POST',
          success: function (res) {
            console.log(res.data);
            if (res.data.pass) {
              wx.setStorageSync('order_id', res.data.order_id);
              that.getPreOrder(token, res.data.order_id); //调用getPreOrder
            }
            else {
              console.log('订单未创建成功');
            }
          }
        })
      },
    
      getPreOrder: function (token, orderID) {
        if (token) {
          wx.request({
            url: baseUrl + '/pay/pre_order',
            method: 'POST',
            header: {
              token: token
            },
            data: {
              id: orderID
            },
            success: function (res) {
              var preData = res.data;
              console.log(preData);
              
              wx.requestPayment({    //请求支付
                timeStamp: preData.timeStamp.toString(),
                nonceStr: preData.nonceStr,
                package: preData.package,
                signType: preData.signType,
                paySign: preData.paySign,
                success: function (res) {
                  console.log(res.data);     
                },
                fail: function (error) {
                  console.log(error);
                }
              })
            }
          })
        }
      },

    如果一切正常的话,在微信开发者工具就会显示这个二维码,


    如果在真机上测试的话,就会直接弹出支付页面。小程序会直接显示支付成功或者失败的页面,然后微信服务器就会开始访问我们之前设置的支付回调地址来推送支付结果,根据结果可以来更新订单的状态。这里我就不写业务逻辑了,大概讲一下就好。

    五,支付回调

    实际上我们需要重写WxPayNotify类的NotifyProcess方法,这里记得Loader::impor()引入那个入口类。

    /**
    	 * 
    	 * 回调方法入口,子类可重写该方法
    	 * 注意:
    	 * 1、微信回调超时时间为2s,建议用户使用异步处理流程,确认成功之后立刻回复微信服务器
    	 * 2、微信服务器在调用失败或者接到回包为非确认包的时候,会发起重试,需确保你的回调是可以重入
    	 * @param array $data 回调解释出的参数
    	 * @param string $msg 如果回调处理失败,可以将错误信息输出到该方法
    	 * @return true 回调出来完成不需要继续回调,false回调处理未完成需要继续回调
    	 */
    	public function NotifyProcess($data, &$msg)
    	{
    		//TODO 用户基础该类之后需要重写该方法,成功的时候返回true,失败返回false
    		return true;
    	}

      也就是说你需要写个新类继承WxPayNotify,再重写NotifyProcess方法,根据检查$data['result_code']是否为SUCCESS可以判断成功与否,成功的话你可以根据业务需求写业务逻辑,最后return true 即可。这时候会想,我重写了这个方法后微信怎么调用呢,其实这里微信不是要直接调用这个方法,你应该在微信支付回调的方法中实例化这个新类,然后根据获得的对象去调用Handle()方法。$obj = new 新类(),$obj->Handle()。


    展开全文
  • 待续
  • 小程序如何开通微信支付

    万次阅读 2018-05-14 18:24:54
    目前开通微信小程序支付功能有两种方式,一个是你已经有微信商户号的情况下直接绑定一下商户号就可以了,另一个就是需要新申请一个微信支付的商户号。第一种:绑定已有微信支付商户号如果您开通过微信支付商户,绑定...
  • 小程序微信支付功能开发

    万次阅读 2019-03-19 08:44:38
    关于小程序内唤起微信支付功能,不同人有不同的思路,有嵌套H5页面的,也有跳转第三方链接网站的,也有放收钱码等图片的。 今天讲一下微信原生的微信支付功能基础版块,支付页面和支付逻辑。 先上个效果图: 页面...
  • 前面给大家讲过一个借助小程序云开发实现微信支付的,但是那个操作稍微有点繁琐,并且还会经常出现问题,今天就给大家讲一个简单的,并且借助官方支付api实现小程序支付功能。 传送门 借助小程序云开发实现小程序...
  • 微信小程序如何接入微信支付

    万次阅读 2018-02-28 16:18:54
    1. 申请微信支付小程序认证以后,可以在小程序后台,微信支付菜单栏,申请微信支付。填写企业信息和对公账户,微信支付会打一笔随机金额到对公账户,输入金额完成验证后,在线签署协议,这样整个微信支付的申请流程...
  • 小程序微信支付

    2018-03-26 13:01:32
    我用的是laravel框架,用的easywechat扩展包,composer下载:... 我写在了model里面支付的配置:封装的支付代码:然后就是那里需要支付就实例化model然后调用pay方法就好了。支付回调:到这里支付就完成了。...
  • 微信小程序微信支付

    千次阅读 多人点赞 2019-06-24 15:47:12
    - -微信支付之小程序- - 哈喽 我是你们的KingYiFan,一直说把...-~~ 本文介绍小程序微信支付的java服务端~~。 微信小程序支付文档:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_3&ind...
  • 小程序调用微信支付,后台Java打包参数,生成签名等具体流程。 直接用,具体代码都已封装好
  • nodejs实现小程序微信支付

    千次阅读 热门讨论 2019-07-23 14:43:12
    最近做小程序时用到了微信支付很是开心,因为之前支付一直都没有做过,终于又可以学点东西了。于是很开心的去看了下微信小程序的支付接口,没想到,事情基本都是后端做的,前端只要调用wx.requestPayment接口就可以...
  • asp.net版小程序微信支付接口文件,含web.config里参数配置,另二个ashx接口文件,绝对可用,另小程序和内嵌H5,授权登陆请参考sn.txt文件内容咨询解决!
  • 微信小程序微信支付功能--java代码

    千次阅读 2018-07-10 10:45:47
    微信支付开发api文档 2. 初步流程 首先一个最简单的支付功能,大体分为三步 预支付,后台系统跟微信后台交互,给小程序返回参数 统一下单 小程序拿到参数进行预支付 用户确认支付,//跟微信后台交互,这一步我们...
  • 小程序微信支付代码实现

    千次阅读 2018-07-19 15:25:42
    小程序端 触发调用微信支付接口: // 微信支付 goPay : function(e){ var that = this; var pay = e.currentTarget.dataset.pay; var uid = that.data.uid; var address = that.data.select_id; wx.request...
  • 小程序支付系统,系统功能测试完了之后,把这部分资源开源一下吧。内容包括有微信小程序支付、退款等。开发平台在linux上,在makefile上编进去就可以用了。
  • 小程序 微信支付

    千次阅读 热门讨论 2020-07-24 16:46:33
    最近应公司市场部要求,在小程序上加上微信支付分。微信支付分到目前为止还在内测阶段,但已经开始试用了。文档如下: https://pay.weixin.qq.com/wiki/doc/apiv3/payscore.php?chapter=15_6&index=4 因为是...
  • 人人商城小程序微信支付配置

    千次阅读 2020-09-28 18:18:10
    1.打开后台小程序设置 2.在微信支付官网下载证书上传 3.填写apikey(32位)可以使用随机生成:https://suijimimashengcheng.51240.com/ 4.然后在小程序里面测试支付功能是成功的 ...
  • 基于thinkphp的基础。整合:小程序支付、退款、提现等微信支付API的一系列功能
1 2 3 4 5 ... 20
收藏数 38,264
精华内容 15,305
热门标签
关键字:

小程序微信支付