旧版人脸支付接口;获取凭证接口测试类

This commit is contained in:
Kit 2019-09-20 15:00:02 +08:00
parent d532097300
commit 38b56fd552
10 changed files with 159 additions and 20 deletions

View File

@ -384,6 +384,39 @@ public class WeixinPayProxy {
totalFee, createIp, attach, store); totalFee, createIp, attach, store);
} }
/**
* 旧版刷脸支付接口
*
* @param faceCode
* 人脸凭证
* @param body
* 商品或支付单简要描述格式要求门店品牌名-城市分店名-实际商品名称
* @param outTradeNo
* 商户系统内部的订单号,32个字符内可包含字母更换授权码必须要换新的商户订单号
* @param totalFee
* 订单总金额单位为分只能为整数
* @param createIp
* 调用微信支付API的机器IP
* @param openId
* 用户在商户appid 下的唯一标识
* @param attach
* 附加数据在查询API和支付通知中原样返回该字段主要用于商户携带订单的自定义数据
* @return
* @throws WeixinException
* @see <a href=
* "https://pay.weixin.qq.com/wiki/doc/wxfacepay/develop/backend.html#刷脸支付后端接口">
* 刷脸支付后端接口</a>
* @see <a href=
* "https://pay.weixin.qq.com/wiki/doc/wxfacepay/develop/sdk-android.html#人脸支付凭证-getwxpayfacecode"
* 获取人脸支付凭证</a>
*/
public MchPayRequest createFacePayRequest(String faceCode, String body,
String outTradeNo, double totalFee, String createIp, String openId,
String attach) throws WeixinException {
return payApi.createFacePayRequest(faceCode, body, outTradeNo,
totalFee, createIp, openId, attach);
}
/** /**
* 订单查询 * 订单查询
* <p> * <p>

View File

@ -80,19 +80,21 @@ public class PayApi extends MchApi {
throw new WeixinException("tradeType not be empty"); throw new WeixinException("tradeType not be empty");
} }
String tradeType = payPackage.getTradeType().toUpperCase(); String tradeType = payPackage.getTradeType().toUpperCase();
if (TradeType.MICROPAY.name().equals(tradeType)) { if (TradeType.MICROPAY.name().equals(tradeType) || TradeType.FACEPAY.name().equals(tradeType)) {
MchPayPackage _payPackage = new MchPayPackage(payPackage.getBody(), MchPayPackage _payPackage = new MchPayPackage(payPackage.getBody(),
payPackage.getDetail(), payPackage.getOutTradeNo(), payPackage.getDetail(), payPackage.getOutTradeNo(),
DateUtil.formatFee2Yuan(payPackage.getTotalFee()), null, DateUtil.formatFee2Yuan(payPackage.getTotalFee()), null,
null, payPackage.getCreateIp(), null, null, null, payPackage.getCreateIp(), null, payPackage.getOpenId(),
payPackage.getAuthCode(), null, payPackage.getAttach(), payPackage.getAuthCode(), null, payPackage.getAttach(),
null, null, payPackage.getGoodsTag(), null, null, payPackage.getGoodsTag(),
payPackage.getLimitPay(), payPackage.getSubAppId()); payPackage.getLimitPay(), payPackage.getSubAppId(), payPackage.getFaceCode());
super.declareMerchant(_payPackage); super.declareMerchant(_payPackage);
_payPackage.setSign(weixinSignature.sign(_payPackage)); _payPackage.setSign(weixinSignature.sign(_payPackage));
String para = XmlStream.toXML(_payPackage); String para = XmlStream.toXML(_payPackage);
WeixinResponse response = weixinExecutor.post( String url = TradeType.MICROPAY.name().equals(tradeType) ? getRequestUri("micropay_uri") :
getRequestUri("micropay_uri"), para); getRequestUri("facepay_url");
WeixinResponse response = weixinExecutor.post(url, para);
MICROPayRequest microPayRequest = response MICROPayRequest microPayRequest = response
.getAsObject(new TypeReference<MICROPayRequest>() { .getAsObject(new TypeReference<MICROPayRequest>() {
}); });
@ -789,4 +791,27 @@ public class PayApi extends MchApi {
getRequestUri("get_wxpayface_authinfo_uri"), request.toRequestString()); getRequestUri("get_wxpayface_authinfo_uri"), request.toRequestString());
return response.getAsObject(new TypeReference<PayfaceAuthinfo>() {}); return response.getAsObject(new TypeReference<PayfaceAuthinfo>() {});
} }
/**
* 微信旧版刷脸支付
*
* @param faceCode
* @param body
* @param outTradeNo
* @param totalFee
* @param createIp
* @param openId
* @param attach
* @return
* @throws WeixinException
*/
public MchPayRequest createFacePayRequest(String faceCode, String body,
String outTradeNo, double totalFee, String createIp, String openId,
String attach) throws WeixinException {
MchPayPackage payPackage = new MchPayPackage(body, outTradeNo,
totalFee, null, createIp, TradeType.FACEPAY, openId, null,
null, attach);
payPackage.setFaceCode(faceCode);
return createPayRequest(payPackage);
}
} }

View File

@ -4,6 +4,7 @@ import com.foxinmy.weixin4j.pay.model.WeixinPayAccount;
import com.foxinmy.weixin4j.pay.sign.WeixinPaymentSignature; import com.foxinmy.weixin4j.pay.sign.WeixinPaymentSignature;
import com.foxinmy.weixin4j.pay.type.SignType; import com.foxinmy.weixin4j.pay.type.SignType;
import com.foxinmy.weixin4j.util.*; import com.foxinmy.weixin4j.util.*;
import com.foxinmy.weixin4j.xml.XmlStream;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -65,7 +66,7 @@ public class PayfaceAuthinfoRequest {
} }
public String toRequestString(){ public String toRequestString(){
StringBuilder content = new StringBuilder(); /*StringBuilder content = new StringBuilder();
content.append("<xml>"); content.append("<xml>");
content.append(String.format("<appid>%s</appid>", payAccount.getId())); content.append(String.format("<appid>%s</appid>", payAccount.getId()));
content.append(String.format("<mch_id>%s</mch_id>", payAccount.getMchId())); content.append(String.format("<mch_id>%s</mch_id>", payAccount.getMchId()));
@ -87,11 +88,12 @@ public class PayfaceAuthinfoRequest {
if(StringUtil.isNotBlank(attach)){ if(StringUtil.isNotBlank(attach)){
content.append(String.format("<attach><![CDATA[%s]]></attach>", attach)); content.append(String.format("<attach><![CDATA[%s]]></attach>", attach));
} }
content.append("</xml>"); content.append("</xml>");*/
return content.toString(); Map paramsMap = getRequestParam();
return XmlStream.map2xml(paramsMap);
} }
private String getRequestSign(){ private Map<String, String> getRequestParam(){
Map<String, String> map = new HashMap<String, String>(); Map<String, String> map = new HashMap<String, String>();
map.put("appid", payAccount.getId()); map.put("appid", payAccount.getId());
map.put("mch_id", payAccount.getMchId()); map.put("mch_id", payAccount.getMchId());
@ -112,6 +114,9 @@ public class PayfaceAuthinfoRequest {
if(StringUtil.isNotBlank(attach)) { if(StringUtil.isNotBlank(attach)) {
map.put("attach", attach); map.put("attach", attach);
} }
return paymentSignature.sign(map); String sign = paymentSignature.sign(map);
map.put("sign", sign);
return map;
} }
} }

View File

@ -77,6 +77,10 @@ public class MchPayPackage extends PayPackage {
@JSONField(name = "scene_info") @JSONField(name = "scene_info")
private String sceneInfo; private String sceneInfo;
@XmlElement(name = "face_code")
@JSONField(name = "face_code")
private String faceCode;
protected MchPayPackage() { protected MchPayPackage() {
// jaxb required // jaxb required
} }
@ -110,7 +114,7 @@ public class MchPayPackage extends PayPackage {
String openId, String authCode, String productId, String attach) { String openId, String authCode, String productId, String attach) {
this(body, null, outTradeNo, totalFee, CurrencyType.CNY, notifyUrl, this(body, null, outTradeNo, totalFee, CurrencyType.CNY, notifyUrl,
createIp, tradeType, openId, authCode, productId, attach, null, createIp, tradeType, openId, authCode, productId, attach, null,
null, null, null, null); null, null, null, null, null);
} }
/** /**
@ -151,12 +155,14 @@ public class MchPayPackage extends PayPackage {
* @param subOpenId * @param subOpenId
* 用户在子商户appid下的唯一标识 非必填 * 用户在子商户appid下的唯一标识 非必填
* openid和sub_openid可以选传其中之一如果选择传sub_openid ,则必须传sub_appid * openid和sub_openid可以选传其中之一如果选择传sub_openid ,则必须传sub_appid
* @param faceCode
* 人脸凭证用于旧版刷脸支付
*/ */
public MchPayPackage(String body, String detial, String outTradeNo, public MchPayPackage(String body, String detial, String outTradeNo,
double totalFee, CurrencyType feeType, String notifyUrl, double totalFee, CurrencyType feeType, String notifyUrl,
String createIp, TradeType tradeType, String openId, String createIp, TradeType tradeType, String openId,
String authCode, String productId, String attach, Date timeStart, String authCode, String productId, String attach, Date timeStart,
Date timeExpire, String goodsTag, String limitPay, String subOpenId) { Date timeExpire, String goodsTag, String limitPay, String subOpenId, String faceCode) {
super(body, detial, outTradeNo, totalFee, notifyUrl, createIp, attach, super(body, detial, outTradeNo, totalFee, notifyUrl, createIp, attach,
timeStart, timeExpire, goodsTag); timeStart, timeExpire, goodsTag);
this.tradeType = tradeType != null ? tradeType.name() : null; this.tradeType = tradeType != null ? tradeType.name() : null;
@ -167,6 +173,7 @@ public class MchPayPackage extends PayPackage {
this.productId = productId; this.productId = productId;
this.limitPay = limitPay; this.limitPay = limitPay;
this.subOpenId = subOpenId; this.subOpenId = subOpenId;
this.faceCode = faceCode;
} }
public String getTradeType() { public String getTradeType() {
@ -213,6 +220,14 @@ public class MchPayPackage extends PayPackage {
this.sceneInfo = sceneInfo; this.sceneInfo = sceneInfo;
} }
public String getFaceCode() {
return faceCode;
}
public void setFaceCode(String faceCode) {
this.faceCode = faceCode;
}
@Override @Override
public String toString() { public String toString() {
return "MchPayPackage [tradeType=" + tradeType + ",feeType=" + feeType return "MchPayPackage [tradeType=" + tradeType + ",feeType=" + feeType

View File

@ -44,7 +44,7 @@ public class MerchantTradeResult extends MerchantResult {
/** /**
* 货币类型,符合 ISO 4217 标准的三位字母代码,默认人民币:CNY * 货币类型,符合 ISO 4217 标准的三位字母代码,默认人民币:CNY
* *
* @see com.foxinmy.weixin4j.mp.type.CurrencyType * @see com.foxinmy.weixin4j.pay.type.CurrencyType
*/ */
@XmlElement(name = "fee_type") @XmlElement(name = "fee_type")
@JSONField(name = "fee_type") @JSONField(name = "fee_type")

View File

@ -68,7 +68,7 @@ public class Order extends MerchantTradeResult {
/** /**
* 现金支付货币类型,符合 ISO 4217 标准的三位字母代码,默认人民币:CNY * 现金支付货币类型,符合 ISO 4217 标准的三位字母代码,默认人民币:CNY
* *
* @see com.foxinmy.weixin4j.mp.type.CurrencyType * @see com.foxinmy.weixin4j.pay.type.CurrencyType
*/ */
@XmlElement(name = "cash_fee_type") @XmlElement(name = "cash_fee_type")
@JSONField(name = "cash_fee_type") @JSONField(name = "cash_fee_type")

View File

@ -29,5 +29,9 @@ public enum TradeType {
/** /**
* WAP支付 * WAP支付
*/ */
MWEB; MWEB,
/**
* 刷脸支付
*/
FACEPAY;
} }

View File

@ -56,3 +56,5 @@ customsorder_declare_uri={mch_base_url}/mch/customs/customdeclareorder
customsorder_query_uri={mch_base_url}/mch/customs/customdeclarequery customsorder_query_uri={mch_base_url}/mch/customs/customdeclarequery
# \u5237\u8138\u652F\u4ED8\u4EA4\u4E92\u6D41\u7A0B--\u83B7\u53D6\u8C03\u7528\u51ED\u8BC1 # \u5237\u8138\u652F\u4ED8\u4EA4\u4E92\u6D41\u7A0B--\u83B7\u53D6\u8C03\u7528\u51ED\u8BC1
get_wxpayface_authinfo_uri={payapp_base_url}/face/get_wxpayface_authinfo get_wxpayface_authinfo_uri={payapp_base_url}/face/get_wxpayface_authinfo
# \u65E7\u7248\u5237\u8138\u652F\u4ED8\u63A5\u53E3
facepay_url={mch_base_url}/pay/facepay

View File

@ -0,0 +1,31 @@
package com.foxinmy.weixin4j.pay.test;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.pay.WeixinPayProxy;
import com.foxinmy.weixin4j.pay.model.WeixinPayAccount;
import com.foxinmy.weixin4j.pay.payment.mch.MchPayRequest;
import org.junit.Test;
public class TestFacePay {
@Test
public void test() throws WeixinException {
String appid = "";
String mchid = "";
String paySignKey = "";
WeixinPayAccount payAccount = new WeixinPayAccount(appid, paySignKey, mchid);
WeixinPayProxy proxy = new WeixinPayProxy(payAccount);
String orderNo = "TESTORDER2019092001";
String openId = "oguJRswolIOGg7Vd1VaqGJuDBFAE";
String faceCode = "0f879a6c-5fff-421c-a233-5fac0f4aad12";
MchPayRequest rsp = proxy.createFacePayRequest(faceCode, "测试的人脸支付",
orderNo, 1,
"127.0.0.1", openId, null);
JSONObject obj = (JSONObject) JSON.toJSON(rsp);
}
}

View File

@ -0,0 +1,24 @@
package com.foxinmy.weixin4j.pay.test;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.pay.WeixinPayProxy;
import com.foxinmy.weixin4j.pay.model.WeixinPayAccount;
import com.foxinmy.weixin4j.pay.payment.face.PayfaceAuthinfo;
import org.junit.Assert;
import org.junit.Test;
public class TestGetPayFaceAuthInfo {
@Test
public void test() throws WeixinException {
String appid = "";
String mchid = "";
String paySignKey = "";
String rawData = "7rfwfRXEDBBbs5MjHW67ritEHtQ7AchIcd0E1zfBxmxyIEXA3aiPTdtrZ1I1fXn6Mpyln11al546YOfNK/HXe81b589a9EyAHuoziZmoe+qJFf2ulkwBWOFffnSN05Qy/ykboG4PciO5yvIMlKEEdmqEjj4ck9oBmAKCqXCM2bRDqNEQOuckZGqGsJsM4xyKEZmlL4cLk+/l9xtvOseJccBeDJfkg5fAdwG1z7lX1DThdyb8uRuE3UCvVghQ21KslyIrF9G6rhh3bP83sD//QklJsdf/dapidxkCACfZkGyNl7wFDnjj5bUgwj9pYW3gQBUff606pI9Eh7VoLwFb768DGfSGHVTwQOPeq+Ldu0bAFyuTNFZUBETYnOCZx0ue7ehDmfmFSxyqVfLRhmlMTPHC/AHRVp6wwg1EnQUTRpUltHdn4O3w5B0PRDVlXogdri0WaTDyrYo18GaZvUdCWld09NZboEPknWEgfQfwaF4vow6R4negvKCVna5kNbjDlDRWNaN+AKtHIznnPKWipc6UunBKeMw/kNTced2f73dUEDALGLPE41nnxA7y1uePWMXVJyNGnWxk461/nz6g/NfyJAgIOILrO1wThEhBd6tFAJGQwu366fnN/5eU9XfBzApHE+OIrtYyRLYJHVaAsAeXOy+PvVqMUFkEWJ3iSLJUZhLJYUbnqVEZaIeAvMY0NJ5+E26WvXXhIGr91gPq35aEjuPu4LKbGTw1jgM=";
WeixinPayAccount payAccount = new WeixinPayAccount(appid, paySignKey, mchid);
WeixinPayProxy proxy = new WeixinPayProxy(payAccount);
PayfaceAuthinfo info = proxy.getWxPayfaceAuthinfo("TEST01", "甘坑客家小镇", "TESTDEVICE01", rawData);
System.out.print(info);
Assert.assertEquals("SUCCESS", info.getReturnCode());
}
}