微信支付/退费(服务商)模式

微信支付/退费(服务商)模式

服务商支付都搞定了,普通商户的支付自然就OK了,下面就记录下在服务商下支付的坑!!!吐槽下 官方文档@#¥%& 果然只有自己写的人看的懂

工具类都贴上去了 什么签名boby中文乱码,各种签名失败基本都踩完了

开发前的准备

注册服务号!划重点 一定是服务号
认证完找到微信支付----》服务商申请
在这里插入图片描述
开始配置服务商
1、API密钥 这个很重要,支付的签名验证需要它 这个是在账户中心–》API安全–》API密钥 APIV2 APIV3都可以用
2、下载安全证书,支付功能可忽略。退费需用到安全证书
3、申请服务商的特约商户 即申请需要支付到对应对公账户的商户号
4、给特约商户开通支付权限 退费权限。授权支付域名
特约商户APPID配置 即绑定需要支付的微信小程序

微信服务商支付

首先打开这不够严谨!!!的微信服务商统一下单文档
以下比较坑爹的几个参数参数
1、appid 注意⚠️ 这里是用服务号的appid 不是小程序的
2、mch_id 这里是用服务商的id 在我的账号一栏可以找到
3、sub_appid 这里才是特约商户的小程序的appid
4、sub_openid 其实就是wx.login中获取的的openId
5、sign 此参数为签名参数 需要将需要传递的参数进行排序并且进行md5签名,需要注意的是需添加参数key 即之前设置的服务商API密钥

🆗!!下面调用统一下单接口 获取所谓的prepay_id预支付标识

 SortedMap<Object,Object> parameters= new TreeMap<Object,Object>();
                String body=foodNames.toString()+foodCount+"件餐品";
                parameters.put("appid", PayConst.SERVICE_APPID);
                parameters.put("body",  body);
                parameters.put("mch_id",PayConst.ORDER_ID);
                parameters.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串
                parameters.put("notify_url","外网Ip");//通知地址 异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。
                parameters.put("out_trade_no",out_trade_no);//商户订单号保证唯一
                parameters.put("spbill_create_ip", ip);  //终端IP APP和网页支付提交用户端ip,Native支付填调用微信支付API的机器IP。
                parameters.put("total_fee",CommonUtil.getMoney(totalFee.toString()));//标价金额
                parameters.put("trade_type","JSAPI");
                parameters.put("sub_openid",sub_openid);
                parameters.put("sub_mch_id",PayConst.CONTRIBUTING_MCH_ID);
                parameters.put("sub_appid",PayConst.CONTRIBUTING_APPID);

                String sign=PayCommonUtil.createSign("UTF-8",parameters);//签名
                parameters.put("sign",sign);

                String parametersXml=PayCommonUtil.getRequestXml(parameters);
                logger.info("签名字符串"+parametersXml);


                String result  = CommonUtil.sendPost(PayConst.UNIFIED_ORDER_URL, parametersXml);

                logger.info("微信签名结果"+result);
                Map<String,String> resultMap = WXPayUtil.xmlToMap(result);
                // 预付商品id
                String prepay_id = resultMap.get("prepay_id").toString();
import com.matcheng.common.utils.MD5Util;
import com.matcheng.order.wx.PayConst;
import org.apache.commons.lang.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;

public class PayCommonUtil {
    /**
     * 获取支付随机码
     * @return
     */
    public static String create_nonce_str() {
        return UUID.randomUUID().toString();
    }
    /**
     * 获取微信支付时间戳
     * @return
     */
    public static String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }

    /**
     * 获取预支付ID时  获取随机码
     * @param length
     * @return
     */
    public static String CreateNoncestr(int length) {
        String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        String res = "";
        for (int i = 0; i < length; i++) {
            Random rd = new Random();
            res += chars.indexOf(rd.nextInt(chars.length() - 1));
        }
        return res;
    }

    /**
     * @author Mark
     * @Description:sign签名
     * @param characterEncoding 编码格式
     * @param parameters 请求参数
     * @return
     */
    public static String createSign(String characterEncoding, SortedMap<Object,Object> parameters){
        StringBuffer sb = new StringBuffer();
        Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序(升序)
        Iterator it = es.iterator();
        while(it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();
            String k = (String)entry.getKey();
            Object v = entry.getValue();
            if(null != v && !"".equals(v)
                    && !"sign".equals(k) && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");
            }
        }
        sb.append("key=" + PayConst.ORDER_KEY2);
        String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
        return sign;
    }

    /**
     * @author Mark
     * @Description:将请求参数转换为xml格式的string
     * @param parameters  请求参数
     * @return
     */
    public static String getRequestXml(SortedMap<Object,Object> parameters){
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        Set es = parameters.entrySet();
        Iterator it = es.iterator();
        while(it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();
            String k = (String)entry.getKey();
            String v = (String)entry.getValue();
            if ("attach".equalsIgnoreCase(k)||"body".equalsIgnoreCase(k)||"sign".equalsIgnoreCase(k)) {
                sb.append("<"+k+">"+"<![CDATA["+v+"]]></"+k+">");
            }else {
                sb.append("<"+k+">"+v+"</"+k+">");
            }
        }
        sb.append("</xml>");
        return sb.toString();
    }

}
import net.sf.json.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.io.*;
import java.net.*;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.MessageDigest;
import java.util.*;

public class CommonUtil {


    /**
     * 发起https请求并获取结果
     *
     * @param requestUrl 请求地址
     * @param requestMethod 请求方式(GET、POST)
     * @param outputStr 提交的数据
     * @return JSONObject (通过JSONObject.get(key)的方式获取json对象的属性值)
     */
    public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
        JSONObject jsonObject = null;

        try {
            //创建SSLContext对象,并使用我们指定的信任管理器初始化(证书过滤)
            TrustManager[] tm = { new MyX509TrustManager() };
            //取得SSL的SSLContext实例
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            //初始化SSLContext
            sslContext.init(null, tm, new java.security.SecureRandom());
            //从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            URL url = new URL(requestUrl);
            HttpsURLConnection httpUrlConn=(HttpsURLConnection) url.openConnection();
            httpUrlConn.setSSLSocketFactory(ssf);

            httpUrlConn.setDoOutput(true);
            httpUrlConn.setDoInput(true);
            httpUrlConn.setUseCaches(false);
            //设置请求方式(GET/POST)
            httpUrlConn.setRequestMethod(requestMethod);

	        /*if ("GET".equalsIgnoreCase(requestMethod))
	            httpUrlConn.connect();   */
            //当有数据需要提交时(当outputStr不为null时,向输出流写数据)
            if (null != outputStr) {
                OutputStream outputStream = httpUrlConn.getOutputStream();
                // 注意编码格式,防止中文乱码
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // 将返回的输入流转换成字符串
            InputStream inputStream = httpUrlConn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;
            StringBuffer buffer=new StringBuffer();
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }

            //释放资源
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            inputStream = null;
            httpUrlConn.disconnect();
            jsonObject = JSONObject.fromObject(buffer.toString());
        } catch (ConnectException ce) {
        } catch (Exception e) {
        }
        return jsonObject;
    }


    /**
     * 向指定 URL 发送POST方法的请求
     *
     * @param url      发送请求的 URL
     * @param param
     * @param isJson   是否json包文 发送
     * @return 所代表远程资源的响应结果
     */
    public static String sendPostRefund(String url, String param, boolean isJson) {
        //System.out.println(url+":"+param);
        File certFile = new File("C:\\key\\apiclient_cert.p12");
        String result = "";
        try {
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            FileInputStream instream = new FileInputStream(certFile);
            try {
                keyStore.load(instream, PayConst.ORDER_ID.toCharArray());
            } finally {
                instream.close();
            }
            // Trust own CA and all self-signed certs
            SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, PayConst.ORDER_ID.toCharArray()).build();
            // Allow TLSv1 protocol only
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,
                    new String[]{"TLSv1"}, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier());

            CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
            HttpPost httppost = new HttpPost(url);


            StringEntity se = new StringEntity(param, "UTF-8");
            se.setContentEncoding("UTF-8");
//            if (isJson)
           se.setContentType("application/json");//发送json数据需要设置contentType

            httppost.addHeader("Accept-Charset", "UTF-8");
            httppost.addHeader("Content-Type", "application/json; charset=utf-8");

            httppost.setEntity(se);
//            System.out.println("executing request" + httppost.getRequestLine());
            CloseableHttpResponse responseEntry = httpclient.execute(httppost);

            HttpEntity entity = responseEntry.getEntity();
//            System.out.println("executing response:" + responseEntry.getStatusLine());
            result = EntityUtils.toString(entity, "UTF-8");
        } catch (Exception e) {
            //System.out.println("发送 POST 请求出现异常!" + e);
            e.printStackTrace();
        }
        return result;
    }


    /**
     * 发送https请求
     * @param requestUrl 请求地址
     * @param requestMethod 请求方式(GET、POST)
     * @param outputStr 提交的数据
     * @return 返回微信服务器响应的信息
     */
    public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {
        try {
            // 创建SSLContext对象,并使用我们指定的信任管理器初始化
            TrustManager[] tm = { new MyX509TrustManager() };
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();
            URL url = new URL(requestUrl);
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.setSSLSocketFactory(ssf);
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            // 设置请求方式(GET/POST)
            conn.setRequestMethod(requestMethod);
            conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
            // 当outputStr不为null时向输出流写数据
            if (null != outputStr) {
                OutputStream outputStream = conn.getOutputStream();
                // 注意编码格式
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }
            // 从输入流读取返回内容
            InputStream inputStream = conn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;
            StringBuffer buffer = new StringBuffer();
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            // 释放资源
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            inputStream = null;
            conn.disconnect();
            return buffer.toString();
        } catch (ConnectException ce) {
        } catch (Exception e) {
        }
        return null;
    }


    /**
     * 获取预支付ID时  获取随机码
     * @param
     * @return
     */
    public static String CreateNoncestr() {
        String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        String res = "";
        for (int i = 0; i < 16; i++) {
            Random rd = new Random();
            res += chars.charAt(rd.nextInt(chars.length() - 1));
        }
        return res;
    }
    /**
     * @author Mark
     * @Description:sign签名
     * @param characterEncoding 编码格式
     * @param parameters 请求参数
     * @return
     */
    public static String createSign(String characterEncoding, HashMap<String,String> parameters){
        StringBuffer sb = new StringBuffer();
        Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序(升序)
        Iterator it = es.iterator();
        while(it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();
            String k = (String)entry.getKey();
            Object v = entry.getValue();
            if(null != v && !"".equals(v)
                    && !"sign".equals(k) && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");
            }
        }
        sb.append("key=" + PayConst.ORDER_KEY2);
        String sign = MD5Encode(sb.toString(), characterEncoding).toUpperCase();
        return sign;
    }

    public static String MD5Encode(String origin, String charsetname) {
        String resultString = null;
        try {
            resultString = new String(origin);
            MessageDigest md = MessageDigest.getInstance("MD5");
            if (charsetname == null || "".equals(charsetname))
                resultString = byteArrayToHexString(md.digest(resultString
                        .getBytes()));
            else
                resultString = byteArrayToHexString(md.digest(resultString
                        .getBytes(charsetname)));
        } catch (Exception exception) {
        }
        return resultString;
    }

    private static String byteArrayToHexString(byte b[]) {
        StringBuffer resultSb = new StringBuffer();
        for (int i = 0; i < b.length; i++)
            resultSb.append(byteToHexString(b[i]));

        return resultSb.toString();
    }

    private static String byteToHexString(byte b) {
        int n = b;
        if (n < 0)
            n += 256;
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigits[d1] + hexDigits[d2];
    }

    private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
            "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };



    /**
     * 获取域名对应的IP地址
     *
     * @param domainName
     * @return
     */
    public static String getIpFromName(String domainName) {
        try {
            return InetAddress.getByName(domainName).getHostAddress();
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return "127.0.0.1";
        }
    }

    /**
     * 向指定URL发送GET方法的请求
     *
     * @param url
     *            发送请求的URL
     * @param param
     *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
     * @return URL 所代表远程资源的响应结果
     */
    public static String sendGet(String url, String param) {
        String result = "";
        BufferedReader in = null;
        try {
            String urlNameString = url + "?" + param;
            System.out.println(urlNameString);
            URL realUrl = new URL(urlNameString);
            // 打开和URL之间的连接
            URLConnection connection = realUrl.openConnection();
            // 设置通用的请求属性
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 建立实际的连接
            connection.connect();
            // 获取所有响应头字段
            Map<String, List<String>> map = connection.getHeaderFields();
            // 遍历所有的响应头字段
            for (String key : map.keySet()) {
                System.out.println(key + "--->" + map.get(key));
            }
            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(
                    connection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送GET请求出现异常!" + e);
            e.printStackTrace();
        }
        // 使用finally块来关闭输入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 向指定 URL 发送POST方法的请求
     *
     * @param url
     *            发送请求的 URL
     * @param param
     *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
     * @return 所代表远程资源的响应结果
     */
    public static String sendPost(String url, String param) {
        //System.out.println(url+":"+param);
        OutputStream out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
            conn.setRequestProperty("Accept-Charset", "UTF-8");
            conn.setRequestProperty("Accept", "application/json;charset=UTF-8");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            conn.connect();
            out = conn.getOutputStream();
            // 发送请求参数
            out.write(param.getBytes("UTF-8"));
            // flush输出流的缓冲
            out.flush();
            out.close();

            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream(), "UTF-8"));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {

            //System.out.println("发送 POST 请求出现异常!" + e);
            e.printStackTrace();
        }
        //使用finally块来关闭输出流、输入流
        finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }



    /**
     * 元转换成分
     * @param amount
     * @return
     */
    public static String getMoney(String amount) {
        if(amount==null){
            return "";
        }
        // 金额转化为分为单位
        // 处理包含, ¥ 或者$的金额
        String currency =  amount.replaceAll("\\$|\\¥|\\,", "");
        int index = currency.indexOf(".");
        int length = currency.length();
        Long amLong = 0l;
        if(index == -1){
            amLong = Long.valueOf(currency+"00");
        }else if(length - index >= 3){
            amLong = Long.valueOf((currency.substring(0, index+3)).replace(".", ""));
        }else if(length - index == 2){
            amLong = Long.valueOf((currency.substring(0, index+2)).replace(".", "")+0);
        }else{
            amLong = Long.valueOf((currency.substring(0, index+1)).replace(".", "")+"00");
        }
        return amLong.toString();
    }



}

不出意外prepay_id 值已经成功获取到了。 当然在调试的过程中遇到了各种问题。
商户ID与APPID不匹配
sub_openid and sub_appid not match
签名失败
等错误.
首先~ 你得保证,你的sign签名没有问题. 顺序正确,没有传入空值,不存在大小写错误,在签名验证工具中可以通过.如果还是报错签名失败!!!!!返到服务商配置,APIV2 或者APIV3密钥反复修改吧。2~3次就可以了

在这里插入图片描述

--------------------------------------------分割线------------------------------------------------------
OKK!!!!!小程序开始调起微信支付 激动人心的时候
还是先看一下文档 [微信小程序支付文档]
(https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_4.shtml)
以下参数注意!!!
1)appId为特约商户的小程序ID千万不要弄混了
2)key 就是服务商APIV2 或者APIV3的密钥
3) 其他参数没什么好说的,paySign 此参数巨坑!! 请注意

首先进行此参数拼接 先看文档–https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_7&index=3

   // 预付商品id
                String prepay_id = resultMap.get("prepay_id").toString();

                SortedMap<Object,Object> payMap = new TreeMap<>();
                payMap.put("appId", PayConst.CONTRIBUTING_APPID); //特约商户下的小程序appId
                payMap.put("nonceStr",out_trade_no);
                payMap.put("package", "prepay_id="+prepay_id);
                payMap.put("signType", "MD5");
                payMap.put("timeStamp", PayCommonUtil.create_timestamp());

                //二次签名
                String paySign= PayCommonUtil.createSign("UTF-8",payMap);

ok 到现在 支付所需要的值都已经全部拿到了,小程序那边直接发起支付就OK了
扣钱 美滋滋

  //提交微信支付
  pay:function(){
    let _this=this
    wx.requestPayment({
      appId:"小程序APPId",
      timeStamp: _this.data.payObject.timeStamp,
      nonceStr: _this.data.payObject.nonceStr,
      package:_this.data.payObject.package,
      signType:_this.data.payObject.signType,
      paySign:_this.data.payObject.sign,
    success:function(event){
      console.log(event)
      wx.showToast({
        title: '支付成功',
        icon:'success',
        duration:2000,
        complete: function () {
     
     //支付成功后的逻辑
         
        }
      })
    },
    fail:function(error){
      console.log("支付失败")
      console.log(error)
    },
    })
  }

在这里插入图片描述
至此 微信支付结束

微信退费

支付都已经OK了 退费肯定就是小意思啦~~,参数直接调用,带上我们的安全证书即可
直接上代码

  //元转分
        String sum= query.getString("sum");
        BigDecimal bigDecimal = new BigDecimal(sum).setScale(2);
        Integer amount=bigDecimal.multiply(new BigDecimal(100)).intValue();

        refunds.put("appid", PayConst.SERVICE_APPID); //服务号ID
        refunds.put("mch_id", PayConst.ORDER_ID); //商户号
        refunds.put("sub_mch_id", PayConst.CONTRIBUTING_MCH_ID); //子商户号
        refunds.put("nonce_str", WXPayUtil.generateNonceStr()+""); //随机字符串
        refunds.put("out_trade_no",query.getString("serial"));//微信支付订单号
        refunds.put("out_refund_no", query.getString("serial"));//退款单号
        refunds.put("total_fee",amount+"");
        refunds.put("refund_fee",amount+"");
        refunds.put("refund_desc",query.getString("cancelInit")); //退款原因
        String sign=PayCommonUtil.createSign("UTF-8",refunds);//签名
        refunds.put("sign",sign);

        String parametersXml=PayCommonUtil.getRequestXml(refunds);
        System.out.println(parametersXml);
        String results = CommonUtil.sendPostRefund(PayConst.RETURN_ORDER_URL, parametersXml,true);//统一下单
       logger.info("微信退款返回"+results);

在这里插入图片描述

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PHP微信支付接口是一种用于在网站或应用程序中实现微信支付功能的工具。它支持服务商模式,在这种模式下,开发者可以代替商户接入微信支付,为商户提供支付服务。 通过PHP微信支付接口,服务商可以实现以下功能: 1. 创建子商户:服务商可以通过接口创建子商户,子商户即代表真实的商户,在微信支付平台注册账号后,获取子商户的商户号。 2. 交易支付:服务商可以通过接口发起交易支付请求,包括拉起微信支付页面、生成二维码等方式。用户在微信内完成支付后,服务商可以获取支付结果,并进行相应的业务处理。 3. 查询交易状态:服务商可以查询某笔交易的支付状态,包括已支付、未支付等。 4. 退款服务商可以通过接口进行退款操作,将交易金额退还给用户。 5. 订单查询:服务商可以查询某个商户的订单列表,包括交易时间、金额、状态等信息。 6. 结算功能:服务商可以通过接口进行订单的结算操作,将商户的资金结算到指定的银行账户。 总而言之,PHP微信支付接口支持服务商模式,为服务商提供了丰富的支付功能和业务接口,方便服务商代替商户接入微信支付,进行支付和业务管理。服务商可以通过编写PHP代码,调用相应的接口实现支付功能,并根据业务需要进行支付结果查询、退款、结算等操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值