v1.1 payermax ios第三方支付

This commit is contained in:
2022-10-11 20:18:05 +08:00
parent 61fb414535
commit cedf79db66
21 changed files with 919 additions and 55 deletions

View File

@@ -1750,6 +1750,12 @@ public class Constant {
* 深海活动预警配置
*/
public static final String LUCKY_SEA_PREWARNING_CONFIG = "lucky_sea_prewarning_config";
/**
* h5充值中各区域的配置
*/
public static final String H5_AREA_CHARGE_CONFIG = "h5_area_charge_config";
}
public static class ActiveMq {

View File

@@ -0,0 +1,83 @@
/*
* 文 件 名: ClanPkStatusEnum
* 版 权:
* 描 述: <描述>
* 创建人: H1
* 创建时间: 2021/3/23
* 修改人:
* 修改内容:
* 修改时间:
*/
package com.accompany.payment.constant;
import java.util.Arrays;
import java.util.Optional;
/**
* <br>枚举类描述: 地区货币类型
* <br>功能详细描述:
*
* @date [2021年05月25日]
*/
public enum CurrencyTypeEnum {
CNY("CNY", "CN", "人民币", "¥"),
TWD("TWD", "TW","新台币","NT$"),
HKD("HKD", "HK","港币", "HK$"),
USD("USD", "USA","美元", "$"),
SGD("SGD", "SG","新加坡币", "$"),
MYR("MYR", "MY","马来西亚币", "RM"),
UNKNOW("UNKNOW", "UNKNOW","未知类型", ""),
;
private String value;
private String countryCode;
private String desc;
private String sign;
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
CurrencyTypeEnum(String value, String countryCode, String desc, String sign) {
this.value = value;
this.desc = desc;
this.countryCode = countryCode;
this.sign = sign;
}
public String getCountryCode() {
return countryCode;
}
public void setCountryCode(String countryCode) {
this.countryCode = countryCode;
}
public static CurrencyTypeEnum getByValue(String value) {
Optional<CurrencyTypeEnum> result = Arrays.stream(CurrencyTypeEnum.values()).filter(currencyEnum ->
currencyEnum.value.equalsIgnoreCase(value)).findAny();
if (result.isPresent()) {
return result.get();
}
return UNKNOW;
}
}

View File

@@ -0,0 +1,42 @@
package com.accompany.payment.dto;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
@Data
public class AreaChargeConfigDTO {
@Data
public static class AreaChargeConfigeItem {
private Boolean enable;
private String desc;
private Integer seq;
private List<String> chargeWays;
private List<AreaChargeWayGroup> chargeWayGroups;
private BigDecimal toLocalCommission;
private Boolean useLocalCurrency;
private String localCurrencyCode;
private String localCurrencySign;
}
@Data
public static class AreaChargeWayGroup {
private String groupName;
private List<String> chargeWays;
}
private Map<String, AreaChargeConfigeItem> areaConfig;
}

View File

@@ -11,6 +11,8 @@ public class ChargeProd {
private String country;
private String localCurrencyCode;
private Long money;
private Integer changeGoldRate;
@@ -65,6 +67,14 @@ public class ChargeProd {
this.country = country;
}
public String getLocalCurrencyCode() {
return localCurrencyCode;
}
public void setLocalCurrencyCode(String localCurrencyCode) {
this.localCurrencyCode = localCurrencyCode;
}
public Long getMoney() {
return money;
}

View File

@@ -15,6 +15,8 @@ public class ChargeRecord {
private String channel;
private String paymentType;
private Byte bussType;
private Byte chargeStatus;
@@ -33,6 +35,8 @@ public class ChargeRecord {
private String clientIp;
private String clientDeviceId;
private String wxPubOpenid;
private String subject;
@@ -103,6 +107,14 @@ public class ChargeRecord {
this.channel = channel == null ? null : channel.trim();
}
public String getPaymentType() {
return paymentType;
}
public void setPaymentType(String paymentType) {
this.paymentType = paymentType;
}
public Byte getBussType() {
return bussType;
}
@@ -175,6 +187,14 @@ public class ChargeRecord {
this.clientIp = clientIp == null ? null : clientIp.trim();
}
public String getClientDeviceId() {
return clientDeviceId;
}
public void setClientDeviceId(String clientDeviceId) {
this.clientDeviceId = clientDeviceId;
}
public String getWxPubOpenid() {
return wxPubOpenid;
}

View File

@@ -0,0 +1,123 @@
package com.accompany.payment.payermax;
import com.accompany.common.status.BusiStatus;
import com.accompany.common.utils.BeanUtil;
import com.accompany.core.exception.ServiceException;
import com.accompany.core.service.SysConfService;
import com.accompany.core.util.OkHttpUtils;
import com.accompany.payment.payermax.config.PayermaxConfig;
import com.accompany.payment.payermax.dto.CreateOrderResDTO;
import com.accompany.payment.payermax.params.CreateOrderParams;
import com.accompany.payment.utils.CommonPayUtils;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
@Service
@Slf4j
public class PayermaxService {
@Autowired
private PayermaxConfig payermaxConfig;
@Autowired
private SysConfService sysConfService;
/**
* 调用成功
*/
private static final String RES_CODE_SUCCESS = "0000";
private static final String PAYMENT_DETAIL_FIELD_NAME = "paymentDetail";
private static final String BIZ_TYPE_CUSTOMIZE = "CUSTOMIZE";
private static final String BIZ_TYPE_IN_CB = "IN_CB";
private static final String API_VERSION = "2.3";
private static final String CURRENCY_USD = "USD";
private static final String AREA_CODE_IN = "IN";
public CreateOrderResDTO createOrder(CreateOrderParams params) {
checkCreateOrderParams(params);
String result = null;
try {
Map<String, String> mapParams = toMapCreateOrderParams(params);
log.info("payermax请求参数{}", JSONObject.toJSONString(mapParams));
result = OkHttpUtils.postWithBody(payermaxConfig.getCreateOrderUrl(), mapParams);
log.info("payermax请求结果{}",result);
} catch (Exception e) {
log.error("payermax创建订单失败。params:" + JSONObject.toJSONString(params), e);
throw new ServiceException(BusiStatus.PAYMENT_FAIL);
}
CreateOrderResDTO res = JSONObject.parseObject(result, CreateOrderResDTO.class);
if (!RES_CODE_SUCCESS.equalsIgnoreCase(res.getBizCode())) {
throw new ServiceException(BusiStatus.PAYMENT_FAIL);
}
return res;
}
private Map<String, String> toMapCreateOrderParams(CreateOrderParams params) {
Map<String, String> tmpParams = new HashMap<>();
tmpParams.put("merchantId", payermaxConfig.getMerchantId());
// 印度的bizType固定是IN_CB
tmpParams.put("bizType", AREA_CODE_IN.equalsIgnoreCase(params.getCountryCode())? BIZ_TYPE_IN_CB: BIZ_TYPE_CUSTOMIZE);
tmpParams.put("version", API_VERSION);
tmpParams.put("sign", CommonPayUtils.signParams(tmpParams, "key", payermaxConfig.getSecretKey()));
tmpParams.put("orderId", params.getOrderId());
tmpParams.put("userId", params.getUserId());
tmpParams.put("subject", params.getSubject());
tmpParams.put("countryCode", params.getCountryCode());
tmpParams.put("currency", params.getCurrency());
tmpParams.put("totalAmount", params.getTotalAmount());
tmpParams.put("frontCallBackUrl", params.getFrontCallBackUrl());
if (params.getPaymentDetail() != null) {
tmpParams.put(PAYMENT_DETAIL_FIELD_NAME, JSONObject.toJSONString(params.getPaymentDetail()));
}
log.info("payermax待处理请求参数{}", JSONObject.toJSONString(tmpParams));
Map<String, String> requestParams = tmpParams.keySet().stream().filter(it -> tmpParams.get(it) != null)
.collect(Collectors.toMap(it -> it, it -> {
if (tmpParams.containsKey(it) && tmpParams.get(it) != null) {
return tmpParams.get(it).toString();
} else {
return "";
}
}));
return requestParams;
}
private void checkCreateOrderParams(CreateOrderParams params) {
if (params == null) {
throw new ServiceException(BusiStatus.PARAMERROR);
}
if (params.getTotalAmount() == null || new BigDecimal(params.getTotalAmount()).compareTo(BigDecimal.ZERO) <= 0) {
params.setTotalAmount("0.01");
}
if (StringUtils.isBlank(params.getOrderId())) {
throw new ServiceException(BusiStatus.PARAMERROR, "商户订单号不能为空");
}
if (StringUtils.isBlank(params.getSubject())) {
throw new ServiceException(BusiStatus.PARAMERROR, "商品订单描述不能为空");
}
if (StringUtils.isBlank(params.getCountryCode())) {
throw new ServiceException(BusiStatus.PARAMERROR, "国家代码不能为空");
}
}
}

View File

@@ -0,0 +1,19 @@
package com.accompany.payment.payermax.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties("payermax")
@Data
public class PayermaxConfig {
private String merchantId;
private String secretKey;
private String callBackUrl;
private String createOrderUrl;
}

View File

@@ -0,0 +1,13 @@
package com.accompany.payment.payermax.dto;
import lombok.Data;
@Data
public class BaseResDTO<T> {
private String bizCode;
private String message;
private T data;
}

View File

@@ -0,0 +1,16 @@
package com.accompany.payment.payermax.dto;
import lombok.Data;
@Data
public class CreateOrderResDTO extends BaseResDTO<CreateOrderResDTO.OrderRes> {
@Data
public static class OrderRes {
private String tradeNo;
private String orderId;
private String requestUrl;
private String status;
private String sign;
}
}

View File

@@ -0,0 +1,30 @@
package com.accompany.payment.payermax.params;
import lombok.Data;
@Data
public class CreateOrderParams {
@Data
public static class PaymentDetail {
private String paymentType;
}
private String orderId;
private String userId;
private String subject;
private String countryCode;
private String currency;
private String totalAmount;
private String frontCallBackUrl;
private PaymentDetail paymentDetail;
private String paymentType;
}

View File

@@ -0,0 +1,95 @@
package com.accompany.payment.payermax.params;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.io.Serializable;
@Getter
@Setter
@ToString
@JsonInclude(JsonInclude.Include.NON_NULL)
public class PayCallbackReqVO implements Serializable {
private static final long serialVersionUID = -4984094248339397495L;
/**
* Merchant ID
*/
private String merchantId;
/**
* SHAREit Order No
*/
private String tradeOrderNo;
/**
* Merchant Order No
*/
private String orderId;
/**
* Pay Order Status
*/
private Integer status;
/**
* Country Code
*/
private String countryCode;
/**
* reference
*/
private String reference;
/**
* Error Code
*/
private String errorCode;
/**
* Error Message
*/
private String errorMsg;
/**
* Signature
*/
private String sign;
/**
* Pay Amount
*/
private String payAmount;
/**
* Pay Currency
*/
private String payCurrency;
/**
* Trade Amount
*/
private String totalAmount;
/**
* Trade Currency
*/
private String currency;
/**
* exchange rate
*/
private String exchangeRate;
/**
* paymentType
*/
private String paymentType;
}

View File

@@ -18,8 +18,10 @@ import com.accompany.payment.alipay.AlipayService;
import com.accompany.payment.alipay.YinyouAlipayService;
import com.accompany.payment.config.AliPayConfig;
import com.accompany.payment.config.BaseWxPayConfig;
import com.accompany.payment.constant.CurrencyTypeEnum;
import com.accompany.payment.constant.PayConstant;
import com.accompany.payment.dto.AlipayAgentDTO;
import com.accompany.payment.dto.AreaChargeConfigDTO;
import com.accompany.payment.event.ChargeEvent;
import com.accompany.payment.model.ChargeProd;
import com.accompany.payment.model.ChargeRecord;
@@ -28,6 +30,7 @@ import com.accompany.payment.model.UserVipRecord;
import com.accompany.payment.strategy.PayContext;
import com.accompany.payment.strategy.PayStrategy;
import com.accompany.payment.strategy.factory.PayStrategyFactory;
import com.accompany.payment.utils.ChargeConfigUtils;
import com.accompany.payment.vo.TarotChargeRetVo;
import com.accompany.payment.wxpay.*;
import com.alibaba.fastjson.JSON;
@@ -39,11 +42,13 @@ import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeWapPayResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Map;
@@ -90,25 +95,16 @@ public class PayCenterService {
* @param clientIp 客户端 ip
* @param successUrl 页面成功跳转 url
* @param deviceInfo
* @param paymentType
* @param countryCode
* @return BusiResult
*/
public BusiResult createOrder(
Long uid,
String chargeProdId,
String channel,
String clientIp,
String successUrl,
ChargeProd chargeProd,
Long erbanNo,
String nick,
String openId,
String realName,
String idCardNum, DeviceInfo deviceInfo)
throws Exception {
public BusiResult createOrder(Long uid, String chargeProdId, String channel, String clientIp, String successUrl, ChargeProd chargeProd,
Long erbanNo, String nick, String openId, String realName, String idCardNum, DeviceInfo deviceInfo, String paymentType, String countryCode) throws Exception {
BusiResult<Object> BusiResult = new BusiResult<>(BusiStatus.SUCCESS);
String recordChannel = getChannelUseInRecord(channel);
ChargeRecord chargeRecord =
buildChargeRecord(uid, chargeProdId, recordChannel, clientIp, chargeProd, openId, deviceInfo);
buildChargeRecord(uid, chargeProdId, recordChannel, clientIp, chargeProd, openId, deviceInfo, paymentType, countryCode);
if (isTarotLowChargeAmountOpen()) {
chargeRecord.setAmount(chargeRecord.getAmount()/100);
}
@@ -260,15 +256,12 @@ public class PayCenterService {
* @param clientIp
* @param chargeProd
* @param deviceInfo
* @param paymentType
* @param countryCode
* @return
*/
public ChargeRecord buildChargeRecord(
Long uid,
String chargeProdId,
String channel,
String clientIp,
ChargeProd chargeProd,
String openId, DeviceInfo deviceInfo) {
public ChargeRecord buildChargeRecord(Long uid, String chargeProdId, String channel, String clientIp, ChargeProd chargeProd,
String openId, DeviceInfo deviceInfo, String paymentType, String countryCode) {
String chargeRecordId = UUIDUitl.get();
ChargeRecord chargeRecord = new ChargeRecord();
chargeRecord.setChargeRecordId(chargeRecordId);
@@ -277,11 +270,28 @@ public class PayCenterService {
chargeRecord.setChannel(channel);
chargeRecord.setBussType(Constant.PayBussType.charge);
chargeRecord.setChargeStatus(Constant.ChargeRecordStatus.create);
Long money = chargeProd.getMoney();
// 支付宝充值,以分为单位
Long amount = money * 100;
// //测试生产环境充值1分钱
chargeRecord.setAmount(amount);
if (StringUtils.isBlank(chargeProd.getLocalCurrencyCode()) || CurrencyTypeEnum.USD.getValue().equalsIgnoreCase(chargeProd.getLocalCurrencyCode())) {
// 没有货币代码或货币代码是美元
chargeRecord.setAmount(chargeProd.getMoney());
chargeRecord.setLocalCurrencyCode(CurrencyTypeEnum.USD.getValue());
chargeRecord.setLocalAmount(chargeProd.getMoney());
} else {
AreaChargeConfigDTO.AreaChargeConfigeItem areaChargeConfig = ChargeConfigUtils.getAreaChargeConfig(countryCode);
if (areaChargeConfig == null) {
log.info("充值下单失败相关地区没有配置。countryCode: {}", countryCode);
throw new ServiceException(BusiStatus.PARAMETERILLEGAL);
}
if (areaChargeConfig.getToLocalCommission() == null) {
log.info("充值下单失败没有配置汇率。countryCode: {}", countryCode);
throw new ServiceException(BusiStatus.BUSIERROR);
}
// 本地货币转成美元
chargeRecord.setAmount(new BigDecimal(chargeProd.getMoney()).divide(areaChargeConfig.getToLocalCommission(), 0, BigDecimal.ROUND_DOWN).longValue());
chargeRecord.setLocalAmount(chargeProd.getMoney());
chargeRecord.setLocalCurrencyCode(chargeProd.getLocalCurrencyCode());
}
String body = chargeProd.getProdName() + "充值";
String subject = chargeProd.getProdName() + "充值";
chargeRecord.setSubject(subject);
@@ -290,20 +300,18 @@ public class PayCenterService {
chargeRecord.setCreateTime(Calendar.getInstance().getTime());
chargeRecord.setWxPubOpenid(openId);
if (deviceInfo != null) {
chargeRecord.setClientDeviceId(deviceInfo.getDeviceId());
chargeRecord.setChargeApp(deviceInfo.getApp());
}
chargeRecord.setTotalGold(chargeProd.getChargeGoldNum());
chargeRecord.setPaymentType(paymentType);
chargeRecord.setCountry(countryCode);
return chargeRecord;
}
private PayContext buildPayContext(
Long erbanNo,
String nick,
String successUrl,
ChargeProd chargeProd,
ChargeRecord chargeRecord,
String realName,
String idCardNum, DeviceInfo deviceInfo) {
private PayContext buildPayContext(Long erbanNo, String nick, String successUrl, ChargeProd chargeProd, ChargeRecord chargeRecord,
String realName, String idCardNum, DeviceInfo deviceInfo) {
PayContext payContext = new PayContext();
payContext.setErbanNo(erbanNo);
payContext.setNick(nick);
@@ -439,10 +447,7 @@ public class PayCenterService {
chargeRecord.setBussType(Constant.PayBussType.OPEN_VIP);
chargeRecord.setChargeStatus(Constant.ChargeRecordStatus.create);
chargeRecord.setWxPubOpenid(openId);
Long money = chargeProd.getMoney();
// 充值金额,以分为单位
Long amount = money * 100;
chargeRecord.setAmount(amount);
chargeRecord.setAmount(chargeProd.getMoney());
String body = chargeProd.getProdName();
String subject = chargeProd.getProdName();
chargeRecord.setSubject(subject);
@@ -450,6 +455,7 @@ public class PayCenterService {
chargeRecord.setClientIp(clientIp);
chargeRecord.setCreateTime(Calendar.getInstance().getTime());
if (deviceInfo != null) {
chargeRecord.setClientDeviceId(deviceInfo.getDeviceId());
chargeRecord.setChargeApp(deviceInfo.getApp());
}
return chargeRecord;

View File

@@ -0,0 +1,51 @@
package com.accompany.payment.strategy;
import com.accompany.common.constant.Constant;
import com.accompany.payment.annotation.PayChannelSupport;
import com.accompany.payment.constant.PayConstant;
import com.accompany.payment.model.ChargeProd;
import com.accompany.payment.model.ChargeRecord;
import com.accompany.payment.payermax.PayermaxService;
import com.accompany.payment.payermax.dto.CreateOrderResDTO;
import com.accompany.payment.payermax.params.CreateOrderParams;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
@Service
@PayChannelSupport(Constant.ChargeChannel.payermax)
public class PayerMaxStrategy extends AbstractPayStrategy {
@Autowired
private PayermaxService payermaxService;
@Override
public Object pay(PayContext context) throws Exception {
ChargeRecord chargeRecord = context.getChargeRecord();
ChargeProd chargeProd = context.getChargeProd();
CreateOrderParams params = new CreateOrderParams();
params.setOrderId(chargeRecord.getChargeRecordId());
params.setUserId(chargeRecord.getUid().toString());
params.setCountryCode(chargeRecord.getCountry());
params.setCurrency(chargeRecord.getLocalCurrencyCode());
params.setTotalAmount(new BigDecimal(chargeRecord.getAmount()).divide(Constant.HUNDRED, 2, BigDecimal.ROUND_HALF_UP).toString());
params.setSubject(chargeProd.getProdName());
params.setFrontCallBackUrl(context.getSuccessUrl());
CreateOrderParams.PaymentDetail paymentDetail = new CreateOrderParams.PaymentDetail();
paymentDetail.setPaymentType(chargeRecord.getPaymentType());
params.setPaymentDetail(paymentDetail);
CreateOrderResDTO orderRes = payermaxService.createOrder(params);
Map<String, Object> appMap = new HashMap<>();
appMap.put(PayConstant.H5_PAY_URL_FIELD, orderRes.getData().getRequestUrl());
appMap.put(PayConstant.H5_PAY_NICK_FIELD, context.getNick());
appMap.put(PayConstant.H5_PAY_ERBANNO_FIELD, context.getErbanNo());
return appMap;
}
}

View File

@@ -0,0 +1,35 @@
package com.accompany.payment.utils;
import com.accompany.common.constant.Constant;
import com.accompany.core.service.SysConfService;
import com.accompany.payment.dto.AreaChargeConfigDTO;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Component
public final class ChargeConfigUtils {
private static SysConfService sysConfService;
@Autowired
private void setSysConfService(SysConfService sysConfService) {
ChargeConfigUtils.sysConfService = sysConfService;
}
public static AreaChargeConfigDTO.AreaChargeConfigeItem getAreaChargeConfig(String countryCode) {
AreaChargeConfigDTO h5AreaChargeConfig = JSONObject.parseObject(sysConfService.getDefaultSysConfValueById(Constant.SysConfId.H5_AREA_CHARGE_CONFIG, "{}"), AreaChargeConfigDTO.class);
Map<String, AreaChargeConfigDTO.AreaChargeConfigeItem> areaConfigMap = h5AreaChargeConfig.getAreaConfig();
if (areaConfigMap == null) {
areaConfigMap = new HashMap<>();
}
AreaChargeConfigDTO.AreaChargeConfigeItem areaChargeConfig = areaConfigMap.get(countryCode);
return areaChargeConfig;
}
}

View File

@@ -0,0 +1,160 @@
package com.accompany.payment.utils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;
import java.security.MessageDigest;
import java.util.*;
/**
* TODO 对外提供签名工具类方法以及使用示例
*
* @author xinxiang_jiang@foxmail.com
*/
public class SignMD5Utils {
/**
* 根据请求参数生成签名请求参数排序并后面补充key值最后进行MD5加密返回大写结果
*
* @param params 请求参数
* @param key 约定Key值
* @return 返回签名sign
*/
public static String signForMD5(Map<String, Object> params, String key) {
String signatures = "";
try {
String s = formatMapToSignStr(params);
System.out.println(s);
signatures = getMD5(s + "&key=" + key).toUpperCase();
} catch (Exception e) {
e.printStackTrace();
}
return signatures;
}
/**
* 验证sign是否正确
*
* @param paraMap 请求参数
* @param sign 传入的sign
* @param key 约定秘钥
* @return 返回是否正确
*/
public static boolean verifyForMD5(Map<String, Object> paraMap, String sign, String key) {
String signFromParams = signForMD5(paraMap, key);
return sign.equals(signFromParams);
}
/**
* 根据参数字符串生成加密后字符串
*
* @param message
* @return
*/
@SuppressWarnings("All")
public static String getMD5(String message) {
String md5 = "";
try {
// 创建一个md5算法对象
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] messageByte = message.getBytes("UTF-8");
// 获得MD5字节数组,16*8=128位
byte[] md5Byte = md.digest(messageByte);
// 转换为16进制字符串
md5 = bytesToHex(md5Byte);
} catch (Exception e) {
e.printStackTrace();
}
return md5;
}
/**
* 2进制转16进制
*
* @param bytes 字节数组
* @return 返回十六进制字符串
*/
@SuppressWarnings("All")
public static String bytesToHex(byte[] bytes) {
StringBuffer hexStr = new StringBuffer();
int num;
for (int i = 0; i < bytes.length; i++) {
num = bytes[i];
if (num < 0) {
num += 256;
}
if (num < 16) {
hexStr.append("0");
}
hexStr.append(Integer.toHexString(num));
}
return hexStr.toString().toUpperCase();
}
@SuppressWarnings("All")
private static String formatMapToSignStr(Map<String, Object> paramMap) {
String buff = "";
Map tmpMap = paramMap;
List<Map.Entry> infoIds = new ArrayList(tmpMap.entrySet());
Collections.sort(infoIds, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return (((Map.Entry<String, Object>) o1).getKey()).toString().compareTo(((Map.Entry<String, Object>) o2).getKey());
}
});
StringBuffer buf = new StringBuffer();
for (Map.Entry item : infoIds) {
if ((!StringUtils.isEmpty((String) item.getKey()))
&& (!("sign".equals(item.getKey())))) {
String key = (String) item.getKey();
Object val = item.getValue();
if (val instanceof JSONObject || val instanceof HashMap) {
buf.append(key + "=" + formatMapToSignStr((Map) val));
buf.append("&");
} else if(val instanceof JSONArray){
for (int i = 0; i < ((JSONArray) val).size(); i++) {
buf.append(key + "=" + formatMapToSignStr(((JSONArray) val).getJSONObject(i)));
buf.append("&");
}
} else {
buf.append(key + "=" + val);
buf.append("&");
}
}
}
buff = buf.toString();
if (!(buff.isEmpty())) {
buff = buff.substring(0, buff.length() - 1);
}
return buff;
}
public static void main(String[] args) {
//演示实例
String merchantMD5Key = "123456789";
Map<String, Object> params = new HashMap<>(16);
Map<String, Object> aa = new HashMap<>(16);
aa.put("bizType", "test");
Map<String, Object> bb = new HashMap<>(16);
bb.put("version", "test");
List<Map<String, Object>> a = Arrays.asList(aa,bb);
params.put("bizType", "test");
params.put("version", "2.0");
params.put("merchantId", "SP4189603");
params.put("orderId", "1535433516149");
params.put("amount", "13.6");
params.put("currency", "INR");
params.put("countryCode", a);
String sign = signForMD5(params, merchantMD5Key);
params.put("sign", sign);
System.out.println("this is your request params with sign: " + params);
boolean flag = verifyForMD5(params, sign, merchantMD5Key);
System.out.println("verify sign result is: " + flag);
}
}

View File

@@ -6,6 +6,8 @@
<result column="prod_name" property="prodName" jdbcType="VARCHAR"/>
<result column="prod_desc" property="prodDesc" jdbcType="VARCHAR"/>
<result column="prod_status" property="prodStatus" jdbcType="TINYINT"/>
<result column="country" property="country" jdbcType="VARCHAR"/>
<result column="local_currency_code" property="localCurrencyCode" jdbcType="TINYINT"/>
<result column="money" property="money" jdbcType="BIGINT"/>
<result column="change_gold_rate" property="changeGoldRate" jdbcType="INTEGER"/>
<result column="gift_gold_num" property="giftGoldNum" jdbcType="INTEGER"/>
@@ -75,7 +77,7 @@
</where>
</sql>
<sql id="Base_Column_List">
charge_prod_id, prod_name, prod_desc, prod_status, country, money, change_gold_rate, gift_gold_num,
charge_prod_id, prod_name, prod_desc, prod_status, country, local_currency_code, money, change_gold_rate, gift_gold_num,
first_gift_gold_num, channel, seq_no, charge_gold_num
</sql>
<select id="selectByExample" resultMap="BaseResultMap"

View File

@@ -8,10 +8,14 @@
<result column="pingxx_charge_id" property="pingxxChargeId" jdbcType="VARCHAR"/>
<result column="charge_prod_id" property="chargeProdId" jdbcType="VARCHAR"/>
<result column="channel" property="channel" jdbcType="VARCHAR"/>
<result column="payment_type" property="paymentType" jdbcType="VARCHAR"/>
<result column="buss_type" property="bussType" jdbcType="TINYINT"/>
<result column="charge_status" property="chargeStatus" jdbcType="TINYINT"/>
<result column="charge_status_desc" property="chargeStatusDesc" jdbcType="VARCHAR"/>
<result column="amount" property="amount" jdbcType="BIGINT"/>
<result column="country" property="country" jdbcType="VARCHAR"/>
<result column="local_currency_code" property="localCurrencyCode" jdbcType="VARCHAR"/>
<result column="local_amount" property="localAmount" jdbcType="BIGINT"/>
<result column="total_gold" property="totalGold" jdbcType="BIGINT"/>
<result column="client_ip" property="clientIp" jdbcType="VARCHAR"/>
<result column="wx_pub_openid" property="wxPubOpenid" jdbcType="VARCHAR"/>
@@ -168,6 +172,9 @@
<if test="channel != null">
channel,
</if>
<if test="paymentType != null">
payment_type,
</if>
<if test="bussType != null">
buss_type,
</if>
@@ -180,12 +187,24 @@
<if test="amount != null">
amount,
</if>
<if test="country != null">
country,
</if>
<if test="localCurrencyCode != null">
local_currency_code,
</if>
<if test="localAmount != null">
local_amount,
</if>
<if test="totalGold != null">
total_gold,
</if>
<if test="clientIp != null">
client_ip,
</if>
<if test="clientDeviceId != null">
client_device_id,
</if>
<if test="wxPubOpenid != null">
wx_pub_openid,
</if>
@@ -239,6 +258,9 @@
<if test="channel != null">
#{channel,jdbcType=VARCHAR},
</if>
<if test="paymentType != null">
#{paymentType,jdbcType=VARCHAR},
</if>
<if test="bussType != null">
#{bussType,jdbcType=TINYINT},
</if>
@@ -251,12 +273,24 @@
<if test="amount != null">
#{amount,jdbcType=BIGINT},
</if>
<if test="country != null">
#{country,jdbcType=VARCHAR},
</if>
<if test="localCurrencyCode != null">
#{localCurrencyCode,jdbcType=VARCHAR},
</if>
<if test="localAmount != null">
#{localAmount,jdbcType=BIGINT},
</if>
<if test="totalGold != null">
#{totalGold,jdbcType=BIGINT},
</if>
<if test="clientIp != null">
#{clientIp,jdbcType=VARCHAR},
</if>
<if test="clientDeviceId != null">
#{clientDeviceId,jdbcType=VARCHAR},
</if>
<if test="wxPubOpenid != null">
#{wxPubOpenid,jdbcType=VARCHAR},
</if>