微信支付(小程序)-java

 

 

微信支付开发者文档微信支付是腾讯公司的支付业务品牌,微信支付提供公众号支付、APP支付、扫码支付、刷卡支付等支付方式。微信支付结合微信公众账号,全面打通O2O生活消费领域,提供专业的互联网+行业解决方案,微信支付支持微信红包和微信理财通,是移动支付的首选。https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pages/index.shtml

 https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=1_1

微信支付我们来探讨一下 和大家~ (说句实话 微信的官网真的是垃圾乱七八糟的 个人观点 如有雷同 纯属巧合)

 微信的各类说明 文档不够简洁明了 给我的感觉 很乱就 这一点估计也是这个产品团队的人员问题


微信支付 现在有2个版本 一个是v2  v3  ,v3比较新

微信没有沙箱环境,需要是企业。

首先商户平台 开通微信支付

微信支付-开发者文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_1.shtml

 商户系统先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易会话标识后再按Native、JSAPI、APP等不同场景生成交易串调起支付。

参数名 变量 类型[长度限制] 必填 描述
应用ID appid string[1,32] body 由微信生成的应用ID,全局唯一。请求基础下单接口时请注意APPID的应用属性,例如公众号场景下,需使用应用属性为公众号的服务号APPID
示例值:wxd678efh567hg6787
直连商户号 mchid string[1,32] body 直连商户的商户号,由微信支付生成并下发。
示例值:1230000109
商品描述 description string[1,127] body 商品描述
示例值:Image形象店-深圳腾大-QQ公仔
商户订单号 out_trade_no string[6,32] body 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一
示例值:1217752501201407033233368018
交易结束时间 time_expire string[1,64] body 订单失效时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日 13点29分35秒。
示例值:2018-06-08T10:34:56+08:00
附加数据 attach string[1,128] body 附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用,实际情况下只有支付完成状态才会返回该字段。
示例值:自定义数据  
通知地址 notify_url string[1,256] body异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。 公网域名必须为https,如果是走专线接入,使用专线NAT IP或者私有回调域名可使用http
示例值:https://www.weixin.qq.com/wxpay/pay.php
订单优惠标记 goods_tag string[1,32] body 订单优惠标记
示例值:WXG
电子发票入口开放标识 support_fapiao boolean body 传入true时,支付成功消息和支付详情页将出现开票入口。需要在微信支付商户平台或微信公众平台开通电子发票功能,传此字段才可生效。
true:是
false:否
示例值:true
-订单金额 amount object body 订单金额信息
参数名 变量 类型[长度限制] 必填 描述
总金额 total int 订单总金额,单位为分。
示例值:100
货币类型 currency string[1,16] CNY:人民币,境内商户号仅支持人民币。
示例值:CNY
-支付者 payer object body 支付者信息
参数名 变量 类型[长度限制] 必填 描述
用户标识 openid string[1,128] 用户在直连商户appid下的唯一标识。 下单前需获取到用户的Openid,Openid获取详见
示例值:oUpF8uMuAJO_M2pxb1Q9zNjWeS6o
-优惠功能 detail object body 优惠功能
参数名 变量 类型[长度限制] 必填 描述
订单原价 cost_price int 1、商户侧一张小票订单可能被分多次支付,订单原价用于记录整张小票的交易金额。
2、当订单原价与支付金额不相等,则不享受优惠。
3、该字段主要用于防止同一张小票分多次支付,以享受多次优惠的情况,正常支付订单不必上传此参数。
示例值:608800
商品小票ID invoice_id string[1,32] 商家小票ID
示例值:微信123
+单品列表 goods_detail array 单品列表信息
条目个数限制:【1,6000】
-场景信息 scene_info object body 支付场景描述
参数名 变量 类型[长度限制] 必填 描述
用户终端IP payer_client_ip string[1,45] 用户的客户端IP,支持IPv4和IPv6两种格式的IP地址。
示例值:14.23.150.211
商户端设备号 device_id string[1,32] 商户端设备号(门店号或收银设备ID)。
示例值:013467007045764
+商户门店信息 store_info object 商户门店信息
-结算信息 settle_info object body 结算信息
参数名 变量 类型[长度限制] 必填 描述
是否指定分账 profit_sharing boolean 是否指定分账
示例值:false

请求示例

 { "mchid": "1900006XXX", "out_trade_no": "1217752501201407033233368318", "appid": "wxdace645e0bc2cXXX", "description": "Image形象店-深圳腾大-QQ公仔", "notify_url": "https://www.weixin.qq.com/wxpay/pay.php", "amount": { "total": 1, "currency": "CNY" }, "payer": { "openid": "o4GgauInH_RCEdvrrNGrntXDuXXX" } }

返回参数

参数名 变量 类型[长度限制] 必填 描述
预支付交易会话标识 prepay_id string[1,64] 预支付交易会话标识。用于后续接口调用中使用,该值有效期为2小时
示例值:wx201410272009395522657a690389285100

{ "prepay_id": "wx26112221580621e9b071c00d9e093b0000" }

错误码公共错误码

状态码 错误码 描述 解决方案
403 TRADE_ERROR 交易错误 因业务原因交易失败,请查看接口返回的详细信息
500 SYSTEM_ERROR 系统错误 系统异常,请用相同参数重新调用
401 SIGN_ERROR 签名错误 请检查签名参数和方法是否都符合签名算法要求
403 RULE_LIMIT 业务规则限制 因业务规则限制请求频率,请查看接口返回的详细信息
400 PARAM_ERROR 参数错误 请根据接口返回的详细信息检查请求参数
403 OUT_TRADE_NO_USED 商户订单号重复 请核实商户订单号是否重复提交
404 ORDER_NOT_EXIST 订单不存在 请检查订单是否发起过交易
400 ORDER_CLOSED 订单已关闭 当前订单已关闭,请重新下单
500 OPENID_MISMATCH openid和appid不匹配 请确认openid和appid是否匹配
403 NO_AUTH 商户无权限 请商户前往申请此接口相关权限
400 MCH_NOT_EXISTS 商户号不存在 请检查商户号是否正确
500 INVALID_TRANSACTIONID 订单号非法 请检查微信支付订单号是否正确
400 INVALID_REQUEST 无效请求 请根据接口返回的详细信息检查
429 FREQUENCY_LIMITED 频率超限 请降低请求接口频率
500 BANK_ERROR 银行系统异常 银行系统异常,请用相同参数重新调用
400 APPID_MCHID_NOT_MATCH appid和mch_id不匹配 请确认appid和mch_id是否匹配
403 ACCOUNT_ERROR 账号异常 用户账号异常,无需更多操作


微信支付现在分为v2版和v3版
2014年9月10号之前申请的为v2版(旧版本),之后申请的为v3版。

V2版中的参数有

AppID

AppSecret

支付专用签名串PaySignKey

商户号PartnerID

初始密钥PartnerKey

并且包含一个证书文件: 安全证书

V3版中的参数有

AppID

AppSecret

商户号PartnerID

初始密钥PartnerKey

商户号MCHID

申请编号

商户平台登录帐号

商户平台登录密码

包含5个证书文件(证书pkcs12格式、证书pem格式、证书密钥pem格式、CA证书, 安全证书)

如果收到的邮件中没有【支付专用签名串PaySignKey】,表示已经是V3版的微信支付了。

微信支付
微信支付接口的入口也和微信公众平台的产品(公众号、小程序、企业微信)一样,都是统一在微信开放平台的资源中心中,我们其实只需要访问微信开放平台这一个官网,通过资源中心,即可访问到我们所需要对接的所有微信产品的接口文档。
 


 我们需要申请很多证书

获取预支付单号 支付 回调  



@RestController
@Api(tags = "PayController")
@Tag(name = "PayController", description = "微信支付")
@RequestMapping("/v3")
public class PayController {

    @PostMapping("/")
    public Map createOrder(Long amount, String desc,String openId) throws Exception{
        return PayUtil.createOrder(desc,amount,openId);
    }

    @PostMapping("/")
    public Map callBackOrder(HttpServletRequest request) throws Exception{
        System.out.println("微信回调开始返回");
        System.out.println("Wechatpay-Timestamp:"+request.getHeader("Wechatpay-Timestamp"));
        System.out.println("Wechatpay-Nonce:" + request.getHeader("Wechatpay-Nonce"));
        System.out.println("Wechatpay-Signature:" + request.getHeader("Wechatpay-Signature"));
        System.out.println("Wechatpay-Serial:" + request.getHeader("Wechatpay-Serial"));
        Map result = new HashMap();
        result.put("code","FAIL");
        try {
            StringBuilder signStr = new StringBuilder();
            // 请求时间戳\n
            signStr.append(request.getHeader("Wechatpay-Timestamp")).append("\n");
            // 请求随机串\n
            signStr.append(request.getHeader("Wechatpay-Nonce")).append("\n");
            BufferedReader br = request.getReader();
            String str =null;
            StringBuilder builder =new StringBuilder();
            while((str = br.readLine()) !=null){
                builder.append(str);
            }
            System.out.println(builder);
            signStr.append(builder.toString()).append("\n");
            //验证签名
            if(!PayUtil.signVerify(request.getHeader("Wechatpay-Serial"), signStr.toString(), request.getHeader("Wechatpay-Signature"))){
                result.put("message","sign error");
                return result;
            }
            //解密密文
            String decryptOrder = PayUtil.decryptOrder(builder.toString());
            System.out.println(decryptOrder);

            //验证订单
            result.put("message",decryptOrder);
            result.put("code","SUCCESS");
        }catch (IIOException e){
            e.printStackTrace();
        }
        return result;

    }


  
    @PostMapping("/")
    public Map<String, Object> wxPayNotify(HttpServletRequest request) {
        System.out.println("微信回调开始返回");
        System.out.println("Wechatpay-Timestamp:"+request.getHeader("Wechatpay-Timestamp"));
        System.out.println("Wechatpay-Nonce:" + request.getHeader("Wechatpay-Nonce"));
        System.out.println("Wechatpay-Signature:" + request.getHeader("Wechatpay-Signature"));
        System.out.println("Wechatpay-Serial:" + request.getHeader("Wechatpay-Serial"));
        Map result = new HashMap();
        result.put("code", "FAIL");
        BufferedReader reader = null;
        try {
            StringBuilder signStr = new StringBuilder();
            // 请求时间戳\n
            signStr.append(request.getHeader("Wechatpay-Timestamp")).append("\n");
            // 请求随机串\n
            signStr.append(request.getHeader("Wechatpay-Nonce")).append("\n");
            // 请求报文主体\n
            reader = request.getReader();
            String str = null;
            StringBuilder builder = new StringBuilder();
            while ((str = reader.readLine()) != null) {
                builder.append(str);
            }
            System.out.println(builder);
            signStr.append(builder.toString()).append("\n");
            // 1.验签
            if (!V3WXPayUtil.signVerify(request.getHeader("Wechatpay-Serial"), signStr.toString(), request.getHeader("Wechatpay-Signature"))) {
                result.put("message", "sign error");
                return result;
            }
            // 2.解密
            String decryptOrder = V3WXPayUtil.decryptOrder(builder.toString());
            System.out.println(decryptOrder);
            if (StringUtils.isEmpty(decryptOrder)) {
                result.put("message", "verification error");
                return result;
            } else {
                result.put("code", decryptOrder);
            }
            return result;
        } catch (IOException e) {
            e.printStackTrace();
            result.put("code", "FAIL");
            result.put("message", e.getMessage());
            return result;
        }
    }

}

猜你喜欢

转载自blog.csdn.net/s_sos0/article/details/130702285