PHP网站应用 本站源码 ·

优录云支付平台 个人免签约微信/支付宝(源码)

如需购买,联系QQ:1393692890

网址:https://sk.yl8.net

原理介绍

第一步: 安装App

下载 yl8sk_wx Android for 微信收款App

点击下载

下载 yl8sk_zfb Android fro 支付宝收款App

点击下载

配置App

yl8sk App安装好以后,必须开启相关权限,否则yl8sk App无法检测到支付通知。

小米手机配置    部分手机没有制作教程,请参考小米手机配置。

注意:修改手机这些设置的目的是为了在微信和支付宝收到款以后,在手机通知栏出现通知消息同时不让手机进入休眠和结束 yl8sk App、微信、支付宝进程,这样才能保证正常收款。

注意:用于安装 yl8sk App 的这个手机最好放在家里专用,并且一直连上充电线。

第二步: 配置收款码

优录云支付平台的原理是通过安装到手机的App监控手机微信、支付宝的二维码扫码支付到账通知并回调开发者应用。消费者在支付的时候是扫描开发者的个人微信、支付宝收款二维码。

  • 先 注册并且登陆 sk.yl8.net
  • 在 左侧系统菜单(微信/支付宝) 页面,上传你的微信、支付宝 App 直接生成收款二维码,固定金额和不固定金额二维码

注意:优录云支付平台 支持企业支付宝。

注意:在 支付宝 - 我的 - 商家服务 - 商家工具 - 收钱码 可以申请提现免费、永不过期、稳定跳转 的支付宝收款二维码。

注意:当你发起支付请求的时候,系统会自动匹配和支付价格一致的支付二维码,如果没有找到可用的,系统返回错误,可能你的二维码没有配置或者没有配置好。

第三步: API接入

接口签名算法详解

PHP版接口签名

<?php
/**
 * 签名算法
 * @param string $key_id S_KEY(商户KEY)
 * @param array $array 例子:$array = array('amount'=>'1.00','out_trade_no'=>'2018123645787452');
 * @return string
 */
function sign ($key_id, $array) {
    $data = md5(sprintf("%.2f", $array['amount']) . $array['out_trade_no']);
    $key[] ="";
    $box[] ="";
    $pwd_length = strlen($key_id);
    $data_length = strlen($data);

    for ($i = 0; $i < 256; $i++) {
        $key[$i] = ord($key_id[$i % $pwd_length]);
        $box[$i] = $i;
    }

    for ($j = $i = 0; $i < 256; $i++) {
        $j = ($j + $box[$i] + $key[$i]) % 256;
        $tmp = $box[$i];
        $box[$i] = $box[$j];
        $box[$j] = $tmp;
    }

    for ($a = $j = $i = 0; $i < $data_length; $i++) {
        $a = ($a + 1) % 256;
        $j = ($j + $box[$a]) % 256;

        $tmp = $box[$a];
        $box[$a] = $box[$j];
        $box[$j] = $tmp;

        $k = $box[(($box[$a] + $box[$j]) % 256)];
        $cipher .= chr(ord($data[$i]) ^ $k);
    }

    return md5($cipher);
}
              

JAVA版接口签名

public class Sign {
    public static String decry_RC4(byte[] data, String key) {
        if (data == null || key == null) {
            return null;
        }

        return asString(RC4Base(data, key));
    }

    public static String decry_RC4(String data, String key) {
        if (data == null || key == null) {
            return null;
        }

        return new String(RC4Base(HexString2Bytes(data), key));
    }

    public static byte[] encry_RC4_byte(String data, String key) {
        if (data == null || key == null) {
            return null;
        }
        byte b_data[] = data.getBytes();

        return RC4Base(b_data, key);
    }

    public static String encry_RC4_string(String data, String key) {
        if (data == null || key == null) {
            return null;
        }

        return toHexString(asString(encry_RC4_byte(data, key)));
    }

    private static String asString(byte[] buf) {
        StringBuffer strbuf = new StringBuffer(buf.length);
        for (int i = 0; i < buf.length; i++) {
            strbuf.append((char) buf[i]);
        }

        return strbuf.toString();
    }

    private static byte[] initKey(String aKey) {
        byte[] b_key = aKey.getBytes();
        byte state[] = new byte[256];

        for (int i = 0; i < 256; i++) {
            state[i] = (byte) i;
        }
        int index1 = 0;
        int index2 = 0;
        if (b_key == null || b_key.length == 0) {
            return null;
        }
        for (int i = 0; i < 256; i++) {
            index2 = ((b_key[index1] & 0xff) + (state[i] & 0xff) + index2) & 0xff;
            byte tmp = state[i];
            state[i] = state[index2];
            state[index2] = tmp;
            index1 = (index1 + 1) % b_key.length;
        }

        return state;
    }

    private static String toHexString(String s) {
        String str = "";
        for (int i = 0; i < s.length(); i++) {
            int ch = (int) s.charAt(i);
            String s4 = Integer.toHexString(ch & 0xFF);
            if (s4.length() == 1) {
                s4 = '0' + s4;
            }
            str = str + s4;
        }

        return str;// 0x表示十六进制
    }

    private static byte[] HexString2Bytes(String src) {
        int size = src.length();
        byte[] ret = new byte[size / 2];
        byte[] tmp = src.getBytes();
        for (int i = 0; i < size / 2; i++) {
            ret[i] = uniteBytes(tmp[i * 2], tmp[i * 2 + 1]);
        }

        return ret;
    }

    private static byte uniteBytes(byte src0, byte src1) {
        char _b0 = (char) Byte.decode("0x" + new String(new byte[]{src0})).byteValue();
        _b0 = (char) (_b0 << 4);
        char _b1 = (char) Byte.decode("0x" + new String(new byte[]{src1})).byteValue();
        byte ret = (byte) (_b0 ^ _b1);

        return ret;
    }

    private static byte[] RC4Base(byte[] input, String mKkey) {
        int x = 0;
        int y = 0;
        byte key[] = initKey(mKkey);
        int xorIndex;
        byte[] result = new byte[input.length];

        for (int i = 0; i < input.length; i++) {
            x = (x + 1) & 0xff;
            y = ((key[x] & 0xff) + y) & 0xff;
            byte tmp = key[x];
            key[x] = key[y];
            key[y] = tmp;
            xorIndex = ((key[x] & 0xff) + (key[y] & 0xff)) & 0xff;
            result[i] = (byte) (input[i] ^ key[xorIndex]);
        }

        return result;
    }

    public static void main(String[] args) {

    }
}
              

接口说明

平台统一接口

接口URL:https://sk.yl8.net/gateway/index/checkpoint.do
参数说明参数说明(POST)注释示例account_id商户ID、在平台首页右边获取商户ID10000content_type请求过程中返回的网页类型,text (扫码支付 )或 json(获取二维码)textthoroughfare支付通道:wx_fixedcode微信固码,wx_unfixedcode微信非固码,zfb_fixedcode支付宝固码,zfb_unfixedcode支付宝非固码wx_unfixedcodeatype支付类型,该参数在服务版下有效(service_auto),其他可为空参数,微信:1,支付宝:21out_trade_no订单信息,在发起订单时附加的信息,如用户名,充值订单号等字段参数2019062668945robin轮训(暂不支持),2:开启轮训,1:进入单通道模式1keyId设备KEY,在列表里面Important参数下的DEVICE Key一项,如果该请求为轮训模式,则本参数无效,本参数为单通道模式785D239777C4DE7739amount支付金额,在发起时用户填写的支付金额1.00callback_url异步通知地址,在支付完成时,本平台向该地址发起回调请求, 对接方接收到回调后,必须返回 success ,否则默认为回调失败,回调信息会补发3次。https://sk.yl8.net/index/index/callback.dosuccess_url支付成功后网页自动跳转地址,仅在网页类型为text下有效,json会将该参数返回https://sk.yl8.net/index/index/success.doerror_url支付失败时,或支付超时后网页自动跳转地址,仅在网页类型为text下有效,json会将该参数返回https://sk.yl8.net/index/index/error.dosign签名算法,在支付时进行签名算法,详见上方算法d92eff67b3be05f5e61502e96278d01b
              

获取订单API接口Url

微信订单接口URL:https://sk.yl8.net/gateway/pay/automaticWechat.do
支付宝订单接口URL:https://sk.yl8.net/gateway/pay/automaticAlipay.do
调用方法:GET
参数说明(GET)注释示例account_id订单ID、在创建订单时会返回订单ID号、注意,只有json网页类型下才会有返回值10000content_type请求过程中返回的网页类型,text (扫码支付 )或 json(获取二维码)text

              

查询订单状态API文档

微信状态查询接口URL:https://sk.yl8.net/gateway/pay/automaticWechatQuery.do
支付宝状态查询接口URL:https://sk.yl8.net/gateway/pay/automaticAlipayQuery.do
参数说明(GET)注释示例id订单ID、在创建订单时会返回订单ID号、注意,只有json网页类型下才会有返回值10000
              

异步通知返回参数说明

              	参数(Post)说明示例account_name商户登录名(会员名),识别是哪个会员名回调过来的请求优录云支付pay_time支付成功的时间戳(10位)1529775437status支付状态,支付状态只有成功一个状态(success)successamount支付金额1.00out_trade_no订单信息,在发起订单时附加的信息,如用户名,充值订单号等字段参数2019062312410711888trade_no交易流水号,由系统生成的交易流水号2019062312410711888fees手续费(体验版除外),本次回调过程产生的手续费用(已经在平台账户中扣除)0.04sign签名算法,在支付时进行签名算法d92eff67b3be05f5e61502e96278d01bcallback_time回调时间,在回调时产生的时间戳(10位)1529775437type当前订单支付类型,1为微信,2为支付宝1account_key商户KEY(S_KEY)4C61C86ABEBC6243
              

PHP版本接收异步通知

<\?php
//接收异步通知请求demo文件
//签名算法库
include ('sign.php');

//商户名称
$account_name  = $_POST['account_name'];
//支付时间戳
$pay_time  = $_POST['pay_time'];
//支付状态
$status  = $_POST['status'];
//支付金额
$amount  = $_POST['amount'];
//支付时提交的订单信息
$out_trade_no  = $_POST['out_trade_no'];
//平台订单交易流水号
$trade_no  = $_POST['trade_no'];
//该笔交易手续费用
$fees  = $_POST['fees'];
//签名算法
$sign  = $_POST['sign'];
//回调时间戳
$callback_time  = $_POST['callback_time'];
//支付类型
$type = $_POST['type'];
//商户KEY(S_KEY)
$account_key = $_POST['account_key'];


//第一步,检测商户KEY是否一致
if ($account_key != '你的商户KEY') exit('error:key');
//第二步,验证签名是否一致
if (sign('你的商户KEY', ['amount'=>$amount,'out_trade_no'=>$out_trade_no]) != $sign) exit('error:sign');

//下面就可以安全的使用上面的信息给贵公司平台进行入款操作

//支付成功后必须要返回该信息,否则默认为发送失败,补发3次,3次还未返回,则默认为发送失败

echo 'success';

//测试时,将来源请求写入到txt文件,方便分析查看
file_put_contents("callback_log.txt", json_encode($_POST));
              

JAVA版本接收异步通知

package im.jik.demo;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import com.alibaba.fastjson.JSONObject;

import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class Demo {
	private static final String CALLBACK_URL = "http://www.xxxpay.com.com/";
	private static final String SUCCESS_URL = "http://www.xxxpay.com.com/";
	private static final String ERROT_URL = "http://www.xxxpay.com.com/";
	private static final String KEY = "4C61C86ABEBC7249";
	private static OkHttpClient client = new OkHttpClient();

	public static void main(String[] args) {
		HashMap params = new HashMap<>();
		params.put("account_id", "10000");// 商户ID
		params.put("content_type", "json");// 网页类型
		params.put("thoroughfare", "service_auto");// 支付通道
		params.put("out_trade_no", "201806261212440");// 订单信息
		params.put("robin", "2");// 轮训状态 //2开启1关闭
		params.put("amount", "20.01");// 支付金额
		params.put("callback_url", CALLBACK_URL);// 异步通知url
		params.put("success_url", SUCCESS_URL);// 支付成功后跳转到url
		params.put("error_url", ERROT_URL);// 支付失败后跳转到url
		String sign = Demo.getSign("20.01", "201806261212440");
		params.put("sign", sign);// 签名算法
		params.put("type", "1");// 支付类型 //1为微信,2为支付宝
		params.put("keyId", "");// 设备KEY 轮询无需填写

		String order = Demo.post("https://www.xxxpay.com.com", params);
		// 获取结果
		System.out.println("result:" + order);

		JSONObject object = JSONObject.parseObject(order);
		JSONObject object2 = object.getJSONObject("data");
		String order_id = object2.getString("order_id");

		String result = Demo.get("https://www.xxxpay.com.com/gateway/pay/service.do?content_type=json&id=" + order_id);
		System.out.println("result:" + result);
	}

	/**
	 * 
	 * @param account_name
	 *            商户名称
	 * @param pay_time
	 *            支付时间戳
	 * @param status
	 *            支付状态
	 * @param amount
	 *            支付金额
	 * @param out_trade_no
	 *            订单信息
	 * @param trade_no
	 *            交易流水号
	 * @param fees
	 *            该订单手续费
	 * @param sign
	 *            订单签名
	 * @param callback_time
	 *            回调时间
	 * @param type
	 *            支付类型
	 * @param account_key
	 *            商户KEY(S_KEY)
	 * @return
	 */
	public static String notify(String account_name, //
			String pay_time, //
			String status, //
			String amount, //
			String out_trade_no, //
			String trade_no, //
			String fees, //
			String sign, //
			String callback_time, //
			String type, //
			String account_key) {
		//验证key是否正确
		if (!KEY.equalsIgnoreCase(account_key)) {
			return "error";
		}
		//验证签名是否正确
		String s = Demo.getSign(amount, out_trade_no);
		if (!s.equalsIgnoreCase(sign)) {
			return "sign error";
		}
		return "success";
	}

	/**
	 * 获得sign
	 * 
	 * @param amount
	 *            金额
	 * @param orderNo
	 *            订单信息
	 * @return
	 */
	public static String getSign(String amount, String orderNo) {
		String data = amount + orderNo;

		System.out.println("data:" + data);

		String md5Crypt = MD5Utils.md5(data.getBytes());

		System.out.println("md5Crypt:" + md5Crypt);

		byte[] rc4_string = RC4.encry_RC4_byte(md5Crypt, KEY);

		System.out.println("rc4_string:" + rc4_string);

		String sign = MD5Utils.md5(rc4_string);

		System.out.println("sign:" + sign);
		return sign;
	}

	public static String post(String url, Map params) {
		FormBody.Builder builder = new FormBody.Builder();
		for (String key : params.keySet()) {
			builder.add(key, params.get(key).toString());
		}

		RequestBody formBody = builder.build();
		Request request = new Request.Builder().url(url).post(formBody).build();
		String result = null;
		try {
			Response response = client.newCall(request).execute();
			int code = response.code();
			System.err.println("状态码:" + code);
			result = response.body().string();

		} catch (IOException e) {
			e.printStackTrace();
		}
		return result;
	}

	public static String get(String url) {

		Request request = new Request.Builder().url(url).build();
		String json = null;
		okhttp3.Response response = null;
		try {

			response = client.newCall(request).execute();
			json = response.body().string();

		} catch (IOException e) {
			e.printStackTrace();
		}
		return json;
	}
}
              

多手机收款配置=>正在处理中...

FAQ

  • 微信可以像支付宝一样,唤起APP完成支付吗?
  • 用「优录云支付平台」收款安全吗?
  • 「优录云支付平台」稳定吗?会不会掉单?
  • 安装 优录云收款助手 App 的手机需要 root 吗?
  • 为什么要安装App呢,如果手机没电或者没网会怎样?
  • 我用于收款的微信或支付宝账号会不会有什么风险?
  • 可以自定义支付页面吗?
  • 你们平台如何扣费呢?
  • 订单未支付成功会扣除手续费吗?
  • 账户充值的手续费没用完可以提现吗?
  • 用户已经扫码付款,但是我没有收到回调是什么情况呢?
  • 支付二维码过期后用户转账付款,怎么办呢?
  • 支持支付宝官方收钱码吗,提现免费的那种?
  • 用 java 调用接口怎么会提示证书出错呢?
  • 微信收到款后在通知栏怎么没有金额呢,只有到账通知?
  • 优录云支付平台 收款有限额吗?
  • 上传收款二维码数量有限制吗?
  • 支持企业微信买单二维码吗?
  • 我流水这么多,可以免掉套餐费吗?
  • 没用完的余额可以退款吗?

小米手机MIUI配置

1. 开启 优录云收款 APP 通知读取权限

注意:必须开启 优录云收款APP 的通知读取权限,否则无法读取支付通知。
安装 优录云收款APP 后会自动跳转到通知设置页面,请找到「优录云收款APP」,并勾选。
以后要开启,请在系统「设置」-「更多设置」-「系统安全」-「通知读取权限」勾选。

2. 关闭神隐模式 和 关闭休眠

在系统「设置」-「电量和性能」-「神隐模式」- 「应用配置」- 右上角三个点「关闭应用后台智能省电」。

在系统「设置」-「锁屏和密码」-「自动锁屏」- 选择「屏幕永不休眠」。

3. 开启 优录云收款APP、微信、支付宝 的开机自启权限

在系统「设置」-「授权管理」-「自启动管理」- 勾选 优录云收款APP、微信、支付宝 允许自启动。

4. 锁定 优录云收款APP、微信、支付宝 任务,不要被系统自动清理

打开三个应用,然后按 设置键 呼出任务管理,向下拉动应用,锁定应用。

5. 开启 优录云收款APP、微信、支付宝 的全部推送通知

在系统「设置」-「通知和状态栏」-「通知管理」- 找到 优录云收款APP、微信、支付宝 开启所有通知。

6. 关闭 微信勿扰模式

在微信「设置」-「勿扰模式」- 关闭 勿扰模式。

7. 开启 微信收款语音播报

在微信「我」-「钱包」-「收付款」- 「二维码收款」- 点击右上角三个点 开启收款到账语音提醒。

8. 开启 支付宝收付款消息提醒

在支付宝搜索「支付助手」- 点击支付助手右上角图标 - 开启 接收支付消息提醒。

参与评论